var models = require('../models');
var User = models.User;
var Reply = models.Reply;
var Relation = models.Relation;
var Message = models.Message;
var TagCollect = models.TagCollect;
var TopicCollect = models.TopicCollect;
var tag_ctrl = require('./tag');
var topic_ctrl = require('./topic');
var message_ctrl = require('./message');
var Util = require('../libs/util');
var config = require('../config').config;
var EventProxy = require('eventproxy').EventProxy;
var check = require('validator').check;
var sanitize = require('validator').sanitize;
var crypto = require('crypto');

exports.index = function (req, res, next) {
  var user_name = req.params.name;
  get_user_by_name(user_name, function (err, user) {
    if (!user) {
      res.render('notify/notify', {error: '这个用户不存在。'});
      return;
    }
    
    var render = function (recent_topics, recent_replies, relation) {
      user.friendly_create_at = Util.format_date(user.create_at, true);
      res.render('user/index', {
        user: user,
        recent_topics: recent_topics,
        recent_replies: recent_replies,
        relation: relation
      });
    };

    var proxy = new EventProxy();
    proxy.assign('recent_topics', 'recent_replies', 'relation', render);

    var query = {author_id: user._id};
    var opt = {limit: 5, sort: [['create_at', 'desc']]};
    topic_ctrl.get_topics_by_query(query, opt, function (err, recent_topics) {
      if (err) {
        return next(err);
      }
      proxy.trigger('recent_topics', recent_topics);
    });

    Reply.find({author_id: user._id}, function (err, replies) {
      if (err) {
        return next(err);
      }
      var topic_ids = [];
      for (var i = 0; i < replies.length; i++) {
        if (topic_ids.indexOf(replies[i].topic_id.toString()) < 0) {
          topic_ids.push(replies[i].topic_id.toString());
        }
      }
      var query = {_id: {'$in': topic_ids}};
      var opt = {limit: 5, sort: [['create_at', 'desc']]};
      topic_ctrl.get_topics_by_query(query, opt, function (err, topics) {
        if (err) {
          return next(err);
        }
        proxy.trigger('recent_replies', topics);
      });
    });

    if (!req.session.user) {
      proxy.trigger('relation', null);
    } else {
      Relation.findOne({user_id: req.session.user._id, follow_id: user._id}, function (err, doc) {
        if (err) {
          return next(err);
        }
        proxy.trigger('relation', doc);
      });
    }
  });
};

exports.show_stars = function (req, res, next) {
  get_users_by_query({is_star: true}, {}, function (err, stars) {
    if (err) {
      return next(err);
    }
    res.render('user/stars', {stars: stars});
  });   
};

exports.setting = function (req, res, next) {
  if (!req.session.user) {
    res.redirect('home');
    return;
  }
  var method = req.method.toLowerCase();
  if (method !== 'post') {
    get_user_by_id(req.session.user._id, function (err, user) {
      if (err) {
        return next(err);
      }
      if (req.query.save === 'success') {
        user.success = '保存成功。';
      }
      user.error = null;
      return res.render('user/setting', user);
    });
    return;
  }
  // post
  var action = req.body.action;
  if (action === 'change_setting') {
    var name = sanitize(req.body.name).trim();      
    name = sanitize(name).xss();
    var email = sanitize(req.body.email).trim();      
    email = sanitize(email).xss();
    var url = sanitize(req.body.url).trim();      
    url = sanitize(url).xss();
    var profile_image_url = sanitize(sanitize(req.body.profile_image_url).trim()).xss();
    var location = sanitize(req.body.location).trim();      
    location = sanitize(location).xss();
    var signature = sanitize(req.body.signature).trim();      
    signature = sanitize(signature).xss();
    var profile = sanitize(req.body.profile).trim();      
    profile = sanitize(profile).xss();
    var weibo = sanitize(req.body.weibo).trim();      
    weibo = sanitize(weibo).xss();
    var receive_at_mail = req.body.receive_at_mail === 'on' ? true: false;
    var receive_reply_mail = req.body.receive_reply_mail === 'on' ? true: false;

    if (url !== '') {
      try {
        if (url.indexOf('http://') < 0) {
          url = 'http://' + url;
        }
        check(url, '不正确的个人网站。').isUrl();
      } catch (e) {
        res.render('user/setting', {
          error: e.message, 
          name: name, 
          email: email, 
          url: url,
          profile_image_url: profile_image_url,
          location: location,
          signature: signature, 
          profile: profile,
          weibo: weibo,
          receive_at_mail: receive_at_mail,
          receive_reply_mail: receive_reply_mail
        });
        return;
      }
    }
    if (weibo) {
      try {
        if (weibo.indexOf('http://') < 0) {
          weibo = 'http://' + weibo;
        }
        check(weibo, '不正确的微博地址。').isUrl();
      } catch (e) {
        res.render('user/setting', {
          error: e.message,
          name: name,
          email: email,
          url: url,
          profile_image_url: profile_image_url,
          location: location,
          signature: signature,
          profile: profile,
          weibo: weibo,
          receive_at_mail: receive_at_mail,
          receive_reply_mail: receive_reply_mail
        });
        return;
      }
    }

    get_user_by_id(req.session.user._id, function (err, user) {
      if (err) {
        return next(err);
      }
      user.url = url;
      user.profile_image_url = profile_image_url;
      user.location = location;
      user.signature = signature;
      user.profile = profile;
      user.weibo = weibo;
      user.receive_at_mail = receive_at_mail;
      user.receive_reply_mail = receive_reply_mail;
      user.save(function (err) {
        if (err) {
          return next(err);
        }
        return res.redirect('/setting?save=success');
      });
    });

  }
  if (action === 'change_password') {
    var old_pass = sanitize(req.body.old_pass).trim();
    var new_pass = sanitize(req.body.new_pass).trim();

    get_user_by_id(req.session.user._id, function (err, user) {
      if (err) {
        return next(err);
      }
      var md5sum = crypto.createHash('md5');
      md5sum.update(old_pass);
      old_pass = md5sum.digest('hex');

      if (old_pass !== user.pass) {
        res.render('user/setting', {
          error: '当前密码不正确。',
          name: user.name,
          email: user.email,
          url: user.url,
          profile_image_url: user.profile_image_url,
          location: user.location,
          signature: user.signature,
          profile: user.profile,
          weibo: user.weibo,
          receive_at_mail: user.receive_at_mail,
          receive_reply_mail: user.receive_reply_mail
        });
        return;
      }

      md5sum = crypto.createHash('md5');
      md5sum.update(new_pass);
      new_pass = md5sum.digest('hex');

      user.pass = new_pass;
      user.save(function (err) {
        if (err) {
          return next(err);
        }
        res.render('user/setting', {
          success: '密码已被修改。',
          name: user.name,
          email: user.email,
          url: user.url,
          profile_image_url: user.profile_image_url,
          location: user.location,
          signature: user.signature,
          profile: user.profile,
          weibo: user.weibo,
          receive_at_mail: user.receive_at_mail,
          receive_reply_mail: user.receive_reply_mail
        });
        return;

      });
    });
  }
};

exports.follow = function (req, res, next) {
  if (!req.session || !req.session.user) {
    res.send('forbidden!');
    return;
  }
  var follow_id = req.body.follow_id;
  get_user_by_id(follow_id, function (err, user) {
    if (err) {
      return next(err);
    }
    if (!user) {
      res.json({status: 'failed'});
    }
    
    var proxy = new EventProxy();
    var done = function () {
      res.json({ status: 'success' });
    };
    proxy.assign('relation_saved', 'message_saved', done);
    Relation.findOne({user_id: req.session.user._id, follow_id: user._id}, function (err, doc) {
      if (err) {
        return next(err);
      }
      if (doc) {
        res.json({ status: 'success' });
        return;
      }
        
      var relation = new Relation();
      relation.user_id = req.session.user._id;
      relation.follow_id = user._id;
      relation.save();
      proxy.trigger('relation_saved');
        
      get_user_by_id(req.session.user._id, function (err, me) {
        if (err) {
          return next(err);
        }
        me.following_count += 1;
        me.save();
      });

      user.follower_count += 1;
      user.save();

      req.session.user.following_count += 1;
    });

    message_ctrl.send_follow_message(follow_id, req.session.user._id);
    proxy.trigger('message_saved');
  });
};

exports.un_follow = function (req, res, next) {
  if (!req.session || !req.session.user) {
    res.send('forbidden!');
    return;
  }
  var follow_id = req.body.follow_id;
  get_user_by_id(follow_id, function (err, user) {
    if (err) {
      return next(err);
    }
    if (!user) {
      res.json({status: 'failed'});
      return;
    }
    Relation.remove({user_id: req.session.user._id, follow_id: user._id}, function (err) {
      if (err) {
        return next(err);
      }
      res.json({status: 'success'});
    });

    get_user_by_id(req.session.user._id, function (err, me) {
      if (err) {
        return next(err);
      }
      me.following_count -= 1;
      me.save();
    });

    user.follower_count -= 1;
    user.save();

    req.session.user.following_count -= 1;
  });
};

exports.toggle_star = function (req, res, next) {
  if (!req.session.user || !req.session.user.is_admin) {
    res.send('forbidden!</strong>');
    return;
  }
  var user_id = req.body.user_id;
  get_user_by_id(user_id, function (err, user) {
    if (err) {
      return next(err);
    }
    user.is_star = !!user.is_star;
    user.save(function (err) {
      if (err) {
        return next(err);
      }
      res.json({ status: 'success' });
    });
  });
};

exports.get_collect_tags = function (req, res, next) {
  if (!req.session.user) {
    res.redirect('home');
    return;
  }
  TagCollect.find({ user_id: req.session.user._id }, function (err, docs) {
    if (err) {
      return next(err);
    }
    var ids = [];
    for (var i = 0; i < docs.length; i++) {
      ids.push(docs[i].tag_id);
    } 
    tag_ctrl.get_tags_by_ids(ids, function (err, tags) {
      if (err) {
        return next(err);
      }
      res.render('user/collect_tags', { tags: tags });
    });
  });
};

exports.get_collect_topics = function (req, res, next) {
  if (!req.session.user) {
    res.redirect('home');
    return;
  } 

  var page = Number(req.query.page) || 1;
  var limit = config.list_topic_count;

  var render = function (topics, pages) {
    res.render('user/collect_topics', {
      topics: topics,
      current_page: page, 
      pages: pages
    });
  };

  var proxy = new EventProxy();
  proxy.assign('topics', 'pages', render);

  TopicCollect.find({ user_id: req.session.user._id }, function (err, docs) {
    if (err) {
      return next(err);
    }
    var ids = [];
    for (var i = 0; i < docs.length; i++) {
      ids.push(docs[i].topic_id);
    }
    var query = { _id: { '$in': ids } };
    var opt = {
      skip: (page - 1) * limit, 
      limit: limit, 
      sort: [ [ 'create_at', 'desc' ] ] 
    };
    topic_ctrl.get_topics_by_query(query, opt, function (err, topics) {
      if (err) {
        return next(err);
      }
      proxy.trigger('topics', topics);
    });
    topic_ctrl.get_count_by_query(query, function (err, all_topics_count) {
      if (err) {
        return next(err);
      }
      var pages = Math.ceil(all_topics_count / limit);
      proxy.trigger('pages', pages);
    });
  });
};

exports.get_followings = function (req, res, next) {
  if (!req.session.user) {
    res.redirect('home');
    return;
  } 
  Relation.find({user_id: req.session.user._id}, function (err, docs) {
    if (err) {
      return next(err);
    }
    var ids = [];
    for (var i = 0; i < docs.length; i++) {
      ids.push(docs[i].follow_id);
    }
    get_users_by_ids(ids, function (err, users) {
      if (err) {
        return next(err);
      }
      res.render('user/followings', {users: users});
    });
  }); 
};

exports.get_followers = function (req, res, next) {
  if (!req.session.user) {
    res.redirect('home');
    return;
  } 
  Relation.find({follow_id: req.session.user._id}, function (err, docs) {
    if (err) {
      return next(err);
    }
    var ids = [];
    for (var i = 0; i < docs.length; i++) {
      ids.push(docs[i].user_id);
    }
    get_users_by_ids(ids, function (err, users) {
      if (err) {
        return next(err);
      }
      res.render('user/followers', {users: users});
    });
  }); 
};

exports.top100 = function (req, res, next) {
  var opt = {limit: 100, sort: [['score', 'desc']]};
  get_users_by_query({}, opt, function (err, tops) {
    if (err) {
      return next(err);
    }
    res.render('user/top100', {users: tops});
  });
};

exports.list_topics = function (req, res, next) {
  var user_name = req.params.name;
  var page = Number(req.query.page) || 1;
  var limit = config.list_topic_count;

  get_user_by_name(user_name, function (err, user) {
    if (!user) {
      res.render('notify/notify', {error: '这个用户不存在。'});
      return;
    }
    
    var render = function (topics, relation, pages) {
      user.friendly_create_at = Util.format_date(user.create_at, true);
      res.render('user/topics', {
        user: user,
        topics: topics,
        relation: relation,
        current_page: page,
        pages: pages
      });
    };

    var proxy = new EventProxy();
    proxy.assign('topics', 'relation', 'pages', render);

    var query = {'author_id': user._id};
    var opt = {skip: (page - 1) * limit, limit: limit, sort: [['create_at', 'desc']]};
    topic_ctrl.get_topics_by_query(query, opt, function (err, topics) {
      if (err) {
        return next(err);
      }
      proxy.trigger('topics', topics);
    });

    if (!req.session.user) {
      proxy.trigger('relation', null);
    } else {
      Relation.findOne({user_id: req.session.user._id, follow_id: user._id}, function (err, doc) {
        if (err) {
          return next(err);
        }
        proxy.trigger('relation', doc);
      });
    }

    topic_ctrl.get_count_by_query(query, function (err, all_topics_count) {
      if (err) {
        return next(err);
      }
      var pages = Math.ceil(all_topics_count / limit);
      proxy.trigger('pages', pages);
    });
  });
};

exports.list_replies = function (req, res, next) {
  var user_name = req.params.name;
  var page = Number(req.query.page) || 1;
  var limit = config.list_topic_count;

  get_user_by_name(user_name, function (err, user) {
    if (!user) {
      res.render('notify/notify', {error: '这个用户不存在。'});
      return;
    }
    
    var render = function (topics, relation, pages) {
      user.friendly_create_at = Util.format_date(user.create_at, true);
      res.render('user/replies', {
        user: user,
        topics: topics,
        relation: relation,
        current_page: page,
        pages: pages
      });
    };

    var proxy = new EventProxy();
    proxy.assign('topics', 'relation', 'pages', render);

    Reply.find({author_id: user._id}, function (err, replies) {
      if (err) {
        return next(err);
      }
      var topic_ids = [];
      for (var i = 0; i < replies.length; i++) {
        if (topic_ids.indexOf(replies[i].topic_id.toString()) < 0) {
          topic_ids.push(replies[i].topic_id);
        }
      }
      var query = {'_id': {'$in': topic_ids}};
      var opt = {skip: (page - 1) * limit, limit: limit, sort: [['create_at', 'desc']]};
      topic_ctrl.get_topics_by_query(query, opt, function (err, topics) {
        if (err) {
          return next(err);
        }
        proxy.trigger('topics', topics);
      });

      topic_ctrl.get_count_by_query(query, function (err, all_topics_count) {
        if (err) {
          return next(err);
        }
        var pages = Math.ceil(all_topics_count / limit);
        proxy.trigger('pages', pages);
      });
    });

    if (!req.session.user) {
      proxy.trigger('relation', null);
    } else {
      Relation.findOne({user_id: req.session.user._id, follow_id: user._id}, function (err, doc) {
        if (err) {
          return next(err);
        }
        proxy.trigger('relation', doc);
      });
    }
  });
};

function get_user_by_id(id, cb) {
  User.findOne({_id: id}, cb);
}
function get_user_by_name(name, cb) {
  User.findOne({name: name}, cb);
}
function get_user_by_loginname(name, cb) {
  User.findOne({loginname: name}, cb);
}

function get_users_by_ids(ids, cb) {
  User.find({'_id': {'$in': ids}}, cb);
}
function get_users_by_query(query, opt, cb) {
  User.find(query, [], opt, cb);
}
exports.get_user_by_id = get_user_by_id;
exports.get_user_by_name = get_user_by_name;
exports.get_user_by_loginname = get_user_by_loginname;
exports.get_users_by_ids = get_users_by_ids;
exports.get_users_by_query = get_users_by_query;
