'use strict';

var async = require('async');
var db = require('../database');

var user = require('../user');
var posts = require('../posts');
const categories = require('../categories');
var plugins = require('../plugins');
var batch = require('../batch');


module.exports = function (Topics) {
	Topics.delete = async function (tid, uid) {
		await Promise.all([
			Topics.setTopicFields(tid, {
				deleted: 1,
				deleterUid: uid,
				deletedTimestamp: Date.now(),
			}),
			removeTopicPidsFromCid(tid),
		]);
	};

	async function removeTopicPidsFromCid(tid) {
		const [cid, pids] = await Promise.all([
			Topics.getTopicField(tid, 'cid'),
			Topics.getPids(tid),
		]);
		await db.sortedSetRemove('cid:' + cid + ':pids', pids);
		await categories.updateRecentTidForCid(cid);
	}

	async function addTopicPidsToCid(tid) {
		const [cid, pids] = await Promise.all([
			Topics.getTopicField(tid, 'cid'),
			Topics.getPids(tid),
		]);
		let postData = await posts.getPostsFields(pids, ['pid', 'timestamp', 'deleted']);
		postData = postData.filter(post => post && !post.deleted);
		var pidsToAdd = [];
		var scores = [];
		postData.forEach(function (post) {
			pidsToAdd.push(post.pid);
			scores.push(post.timestamp);
		});
		await db.sortedSetAdd('cid:' + cid + ':pids', scores, pidsToAdd);
		await categories.updateRecentTidForCid(cid);
	}

	Topics.restore = async function (tid) {
		await Topics.deleteTopicFields(tid, [
			'deleterUid', 'deletedTimestamp',
		]);
		await Promise.all([
			Topics.setTopicField(tid, 'deleted', 0),
			addTopicPidsToCid(tid),
		]);
	};

	Topics.purgePostsAndTopic = async function (tid, uid) {
		const mainPid = await Topics.getTopicField(tid, 'mainPid');
		await batch.processSortedSet('tid:' + tid + ':posts', function (pids, next) {
			async.eachSeries(pids, function (pid, next) {
				posts.purge(pid, uid, next);
			}, next);
		}, { alwaysStartAt: 0 });
		await posts.purge(mainPid, uid);
		await Topics.purge(tid, uid);
	};

	Topics.purge = async function (tid, uid) {
		const [deletedTopic, tags] = await Promise.all([
			Topics.getTopicData(tid),
			Topics.getTopicTags(tid),
		]);
		if (!deletedTopic) {
			return;
		}
		deletedTopic.tags = tags;
		await deleteFromFollowersIgnorers(tid);

		await Promise.all([
			db.deleteAll([
				'tid:' + tid + ':followers',
				'tid:' + tid + ':ignorers',
				'tid:' + tid + ':posts',
				'tid:' + tid + ':posts:votes',
				'tid:' + tid + ':bookmarks',
				'tid:' + tid + ':posters',
			]),
			db.sortedSetsRemove([
				'topics:tid',
				'topics:recent',
				'topics:posts',
				'topics:views',
				'topics:votes',
			], tid),
			deleteTopicFromCategoryAndUser(tid),
			Topics.deleteTopicTags(tid),
			reduceCounters(tid),
		]);
		plugins.hooks.fire('action:topic.purge', { topic: deletedTopic, uid: uid });
		await db.delete('topic:' + tid);
	};

	async function deleteFromFollowersIgnorers(tid) {
		const [followers, ignorers] = await Promise.all([
			db.getSetMembers('tid:' + tid + ':followers'),
			db.getSetMembers('tid:' + tid + ':ignorers'),
		]);
		const followerKeys = followers.map(uid => 'uid:' + uid + ':followed_tids');
		const ignorerKeys = ignorers.map(uid => 'uid:' + uid + 'ignored_tids');
		await db.sortedSetsRemove(followerKeys.concat(ignorerKeys), tid);
	}

	async function deleteTopicFromCategoryAndUser(tid) {
		const topicData = await Topics.getTopicFields(tid, ['cid', 'uid']);
		await Promise.all([
			db.sortedSetsRemove([
				'cid:' + topicData.cid + ':tids',
				'cid:' + topicData.cid + ':tids:pinned',
				'cid:' + topicData.cid + ':tids:posts',
				'cid:' + topicData.cid + ':tids:lastposttime',
				'cid:' + topicData.cid + ':tids:votes',
				'cid:' + topicData.cid + ':recent_tids',
				'cid:' + topicData.cid + ':uid:' + topicData.uid + ':tids',
				'uid:' + topicData.uid + ':topics',
			], tid),
			user.decrementUserFieldBy(topicData.uid, 'topiccount', 1),
		]);
		await categories.updateRecentTidForCid(topicData.cid);
	}

	async function reduceCounters(tid) {
		var incr = -1;
		await db.incrObjectFieldBy('global', 'topicCount', incr);
		const topicData = await Topics.getTopicFields(tid, ['cid', 'postcount']);
		var postCountChange = incr * topicData.postcount;
		await Promise.all([
			db.incrObjectFieldBy('global', 'postCount', postCountChange),
			db.incrObjectFieldBy('category:' + topicData.cid, 'post_count', postCountChange),
			db.incrObjectFieldBy('category:' + topicData.cid, 'topic_count', incr),
		]);
	}
};
