'use strict';

var async = require('async'),
	winston = require('winston'),

	meta = require('../meta'),
	posts = require('../posts'),
	topics = require('../topics'),
	user = require('../user'),
	helpers = require('./helpers'),
	groups = require('../groups'),
	categories = require('../categories'),
	plugins = require('../plugins');

module.exports = function(privileges) {

	privileges.posts = {};

	privileges.posts.get = function(pids, uid, callback) {
		if (!Array.isArray(pids) || !pids.length) {
			return callback(null, []);
		}

		async.parallel({
			isAdmin: function(next){
				user.isAdministrator(uid, next);
			},
			isModerator: function(next) {
				posts.isModerator(pids, uid, next);
			},
			isOwner: function(next) {
				posts.isOwner(pids, uid, next);
			}
		}, function(err, results) {
			if (err) {
				return callback(err);
			}

			var privileges = [];

			for (var i=0; i<pids.length; ++i) {
				var editable = results.isAdmin || results.isModerator[i] || results.isOwner[i];
				privileges.push({
					editable: editable,
					view_deleted: editable,
					move: results.isAdmin || results.isModerator[i]
				});
			}

			callback(null, privileges);
		});
	};

	privileges.posts.can = function(privilege, pid, uid, callback) {
		posts.getCidByPid(pid, function(err, cid) {
			if (err) {
				return callback(err);
			}

			privileges.categories.can(privilege, cid, uid, callback);
		});
	};

	privileges.posts.filter = function(privilege, pids, uid, callback) {
		if (!Array.isArray(pids) || !pids.length) {
			return callback(null, []);
		}
		posts.getCidsByPids(pids, function(err, cids) {
			if (err) {
				return callback(err);
			}

			pids = pids.map(function(pid, index) {
				return {pid: pid, cid: cids[index]};
			});

			privileges.categories.filterCids(privilege, cids, uid, function(err, cids) {
				if (err) {
					return callback(err);
				}

				pids = pids.filter(function(post) {
					return cids.indexOf(post.cid) !== -1;
				}).map(function(post) {
					return post.pid;
				});

				plugins.fireHook('filter:privileges.posts.filter', {
					privilege: privilege,
					uid: uid,
					pids: pids
				},  function(err, data) {
					callback(err, data ? data.pids : null);
				});
			});
		});
	};

	privileges.posts.canEdit = function(pid, uid, callback) {
		async.parallel({
			isEditable: async.apply(isPostEditable, pid, uid),
			isAdminOrMod: async.apply(isAdminOrMod, pid, uid)
		}, function(err, results) {
			if (err) {
				return callback(err);
			}
			if (results.isAdminOrMod) {
				return callback(null, true);
			}
			if (results.isEditable.isLocked) {
				return callback(new Error('[[error:topic-locked]]'));
			}
			if (results.isEditable.isEditExpired) {
				return callback(new Error('[[error:post-edit-duration-expired, ' + meta.config.postEditDuration + ']]'));
			}
			callback(null, results.isEditable.editable);
		});
	};

	privileges.posts.canMove = function(pid, uid, callback) {
		posts.isMain(pid, function(err, isMain) {
			if (err || isMain) {
				return callback(err || new Error('[[error:cant-move-mainpost]]'));
			}
			isAdminOrMod(pid, uid, callback);
		});
	};

	privileges.posts.canPurge = function(pid, uid, callback) {
		async.waterfall([
			function (next) {
				posts.getCidByPid(pid, next);
			},
			function (cid, next) {
				async.parallel({
					purge: async.apply(privileges.categories.isUserAllowedTo, 'purge', cid, uid),
					owner: async.apply(posts.isOwner, pid, uid),
					isAdminOrMod: async.apply(privileges.categories.isAdminOrMod, cid, uid)
				}, next);
			},
			function (results, next) {
				next(null, results.isAdminOrMod || (results.purge && results.owner));
			}
		], callback);
	};

	function isPostEditable(pid, uid, callback) {
		async.waterfall([
			function(next) {
				posts.getPostFields(pid, ['tid', 'timestamp'], next);
			},
			function(postData, next) {
				var postEditDuration = parseInt(meta.config.postEditDuration, 10);
				if (postEditDuration && Date.now() - parseInt(postData.timestamp, 10) > postEditDuration * 1000) {
					return callback(null, {isEditExpired: true});
				}
				topics.isLocked(postData.tid, next);
			},
			function(isLocked, next) {
				if (isLocked) {
					return callback(null, {isLocked: true});
				}

				posts.isOwner(pid, uid, next);
			},
			function(isOwner, next) {
				next(null, {editable: isOwner});
			}
		], callback);
	}

	function isPostTopicLocked(pid, callback) {
		posts.getPostField(pid, 'tid', function(err, tid) {
			if (err) {
				return callback(err);
			}
			topics.isLocked(tid, callback);
		});
	}

	function isAdminOrMod(pid, uid, callback) {
		helpers.some([
			function(next) {
				posts.getCidByPid(pid, function(err, cid) {
					if (err || !cid) {
						return next(err, false);
					}

					user.isModerator(uid, cid, next);
				});
			},
			function(next) {
				user.isAdministrator(uid, next);
			}
		], callback);
	}
};