/*!
**|  PonkBot Derpibooru Commands
**|
**|  Written by Xaekai
**|  Version 2015.12.19.1225
**|  Copyright 2014-2016
**|
**@preserve
*/

var fs      = require("fs")
var https   = require("https")
var request = require("request")

var Derpibooru = {
	Derpibooru: this,

	useSpoiler        : false,
	pendingExclusions : { "favorites": [], "topscoring": [] },
	pendingInclusions : { "favorites": [], "topscoring": [] },
	cachedStaging     : { "favorites": [], "topscoring": [] },
	cachedReStaging   : { "favorites": [], "topscoring": [] },
	favesData         : { "user": {} },

	pool: new https.Agent({ maxSockets: 6 })
};

Derpibooru.firstRun = function(bot){
	Derpibooru.initialized = true;
	Derpibooru.apikey      = bot.derpibooru;
	Derpibooru.errorcode   = bot.errorcode;
	Derpibooru.embed       = bot.imageEmbed;
	Derpibooru.spoiler     = bot.imageSpoiler;
}

Derpibooru.spoilerCheck = function(item){
	if(Derpibooru.useSpoiler && item.tag_ids.indexOf("26707") > -1){
		return Derpibooru.spoiler;
	}
	return Derpibooru.embed;
}

Derpibooru.formatQuery = function(query){
	return String().concat("https://derpibooru.org/",query,".json?key=",Derpibooru.apikey);
}

Derpibooru.processResult = function(bot, data, hasPermission){
	Derpibooru.commandLock = false;
	if(data["representations"]){
		var image = !hasPermission && data["representations"]["medium"] || data["representations"]["large"];
		// -- The \n is just ignored if Control Characters are disabled.
		return bot.sendChatMsg("[Derpibooru] " + "\n" + "https:" + image + (!hasPermission && Derpibooru.embed || ".pynk"), hasPermission);
		}
	else {
		return bot.sendChatMsg("[Derpibooru] " + Derpibooru.errorcode + "Error: Invalid Image ID: " + search);
	}
}

Derpibooru.singleImage = function(bot, username, data, hasPermission) {
	var search = data.trim().match(/^\d+/)
	if(!search){
		return bot.sendPM(username, "[Derpibooru] { Error: Invaled Command Syntax }");
	}

	Derpibooru.commandLock = true;

	function retrieveImageMetadata(url, callback){
		https.get(url, function(res) {
			var body = '';
	
			if(res.statusCode !== 200){
				Derpibooru.commandLock = false;
				return bot.sendPM(username, "[Derpibooru] { Error: Invalid Image ID }");
			}
			res.on('data', function(chunk) {
				body += chunk;
			});
		
			res.on('end', function() {
				data = JSON.parse(body);
				return callback(bot, data, hasPermission);
			});
		}).on('error', function(e) {
			console.log("Got error: ", e);
			Derpibooru.commandLock = false;
			return bot.sendPM(username, "[Derpibooru] { Error: " + e + " }");
		});
	}

	return retrieveImageMetadata(Derpibooru.formatQuery(search), Derpibooru.processResult)
}

Derpibooru.command = function(bot, username, data, fromIRC, command) {
	if(!Derpibooru.initialized){
		Derpibooru.firstRun(bot);
	}
	if(Derpibooru.commandLock){
		return bot.sendChatMsg("[Derpibooru] { Error: Command Locked. } ");
	}

	bot.checkPermission(username, 2, "X", function(hasPermission){
		if(!hasPermission){
			var user = bot.userlist.filter(function (user) { return user.name == username });
			if(!user.length){ 
				return //bot.sendChatMsg("[DEBUG] User not in list")
			}
			if(user[0].rank < 1 && bot.userlist.length > 35){ 
				return bot.sendPM(username, "Image commands are restricted to registered users when the chat is full.")
			}
		}

		if(bot.dualCooldowns({
			username: username,
			type:     "imageEmbed",
			typeText: "Image Command",
			perUser:  60000,
			global:   5000,
			hasPermission: hasPermission
		})){ return; }
			
		if(!Derpibooru.apikey){
			return bot.sendChatMsg("[Derpibooru] { Error: No API key present }")
		}

		if(data.match(/spoil/) && hasPermission){
			Derpibooru.useSpoiler = !Derpibooru.useSpoiler;
			var state = Derpibooru.useSpoiler && "On" || "Off";
			return bot.sendChatMsg("[Derpibooru] { Spoiler Explicit: " + state + " }");
		}

		// Break other commands down into functions
		switch(command){
			case "booru":      return Derpibooru.singleImage(bot, username, data, hasPermission);
			case "topscoring": return Derpibooru.topscoring(bot, username, data, hasPermission);
			case "favorites":  return Derpibooru.favorites(bot, username, data, hasPermission);
		}
	})
}

Derpibooru.finishCache = function(bot, cache, type){
	if(Derpibooru.pendingExclusions[type].length){
		for (var i = 0; i < Derpibooru.pendingExclusions[type].length; i++) {
			cache = cache.filter(function(m){
				return (!!!~m.tags.split(", ").indexOf(Derpibooru.pendingExclusions[i]))
			})
		};
		if(!cache.length){
			Derpibooru.commandLock = false;
			return bot.sendChatMsg("Filtered query results a zero length set.", true)
		}
	}
	if(Derpibooru.pendingInclusions[type].length){
		for (var i = 0; i < Derpibooru.pendingInclusions[type].length; i++) {
			cache = cache.filter(function(m){
				return (!!~m.tags.split(", ").indexOf(Derpibooru.pendingInclusions[type][i]))
			})
		};
		if(!cache.length){
			Derpibooru.commandLock = false;
			return bot.sendChatMsg("Filtered query results a zero length set.", true)
		}
	}
	Derpibooru.cachedStaging[type] = cache
	Derpibooru.cachedReStaging[type].length=0;
	Derpibooru.commandLock = false;
	return bot.sendChatMsg("Cache filled: " + Derpibooru.cachedStaging[type].length + " items.", true)
}


Derpibooru.cacheParse = function(bot, data, type){
	var pages = 10;
	var filters;

	data = data.replace(/cache ?/,'').trim()
	if(data.match(/pages: ?\d\d?/)){
		pages = data.match(/pages: ?\d\d?/)[0].match(/\d+/)[0]
		data = data.replace(/pages: ?\d\d?/g, '').trim()
		bot.sendChatMsg("Pages specified to " + pages + ".")
	} else {
		bot.sendChatMsg("Pages defaulting to 10.")
	}
	if(data.match(/exclude?:\[([^\]]+)?\]/)){
		filters = data.match(/exclude?:\[([^\]]+)?\]/)[1]
		data = data.replace(/exclude?:\[[^\]]+?\]/).trim()
		if(typeof filters == "undefined"){
			Derpibooru.pendingExclusions[type].length = 0;
			bot.sendChatMsg("Exclusions deactivated.")
		} else {
			Derpibooru.pendingExclusions[type] = filters.split(",").map(Function.prototype.call, String.prototype.trim)
			bot.sendChatMsg("Exclusions set to: "
				+ "["
				+ Derpibooru.pendingExclusions[type].join(",")
				+ "]"
			)
		}
	} else if(Derpibooru.pendingExclusions[type].length){
		bot.sendChatMsg("Exclusions unchanged: "
			+ "["
			+ Derpibooru.pendingExclusions[type].join(",")
			+ "]"
			)
	} else {
		bot.sendChatMsg("No exclusions active")
	}
	if(data.match(/include?:\[([^\]]+)?\]/)){
		filters = data.match(/include?:\[([^\]]+)?\]/)[1]
		data = data.replace(/include?:\[[^\]]+?\]/).trim()
		if(typeof filters == "undefined"){
			Derpibooru.pendingInclusions[type].length = 0;
			bot.sendChatMsg("Inclusions deactivated.")
		} else {
			Derpibooru.pendingInclusions[type] = filters.split(",").map(Function.prototype.call, String.prototype.trim)
			bot.sendChatMsg("Inclusions set to: "
				+ "["
				+ Derpibooru.pendingInclusions[type].join(",")
				+ "]"
			)
		}
	} else if(Derpibooru.pendingInclusions[type].length){
		bot.sendChatMsg("Inclusions unchanged: "
			+ "["
			+ Derpibooru.pendingInclusions[type].join(",")
			+ "]"
			)
	} else {
		bot.sendChatMsg("No inclusions active")
	}
	return pages;
}



Derpibooru.topscoring = function(bot, username, data, hasPermission) {
	var type = "topscoring";

	if(data.match(/cache/)){
		if(!hasPermission){
			bot.sendChatMsg("[Derpibooru] { Error: Insufficient privileges. }");
			return bot.sendChatMsg("/kick " + username);
		}

		Derpibooru.commandLock = true;
		bot.sendChatMsg("[Derpibooru] { Cache Topscoring }")

		var pages = Derpibooru.cacheParse(bot, data, type), waiting = pages, cache = [];
		for (var page = 0; page < pages; page++) {
			var url = String().concat("https://www.derpibooru.org/lists/top_scoring.json?key=",Derpibooru.apikey,"&page=",(page+1),"&perpage=50");
			request({ url: url, pool: Derpibooru.pool }, function(error, response, body){
				if(error){ 
					return bot.sendChatMsg(error, true);
				} else {
					cache = cache.concat(JSON.parse(body).images)                       
				}
				if(--waiting == 0){
					return Derpibooru.finishCache(bot, cache, type);
				}
			});
		};
	}
	else if(Derpibooru.cachedStaging[type].length || Derpibooru.cachedReStaging[type].length){
		if(!Derpibooru.cachedStaging[type].length){
			Derpibooru.cachedStaging[type] = Derpibooru.cachedReStaging[type].slice(); Derpibooru.cachedReStaging[type].length = 0;
		}
		var item = Derpibooru.cachedStaging[type].splice(Math.floor(Math.random() * Derpibooru.cachedStaging[type].length), 1)[0];
		var image = "http:" + item.representations.medium ;
		Derpibooru.cachedReStaging[type].push(item)
		return bot.sendChatMsg("[Derpibooru] { Topscoring } \n" + image + Derpibooru.spoilerCheck(item));
	}
	else
	{
		var page = Math.floor(Math.random()*6)
		var url = String().concat("https://www.derpibooru.org/lists/top_scoring.json?key=",Derpibooru.apikey,"&page=",page,"&perpage=50");
		request({ url: url, pool: Derpibooru.pool }, function(error, response, body){
			if(error){ 
				return bot.sendChatMsg(error, true);
			} else {
				var result = JSON.parse(body);
				result = result.images ; 
				if(result.length > 0){
					var index = Math.floor(Math.random()*result.length);
					var image = "https:" + result[index].representations.medium ;
					return bot.sendChatMsg("[Derpibooru] { Topscoring } \n" + image + Derpibooru.spoilerCheck(result[index]));
				}
				else {
					return bot.sendChatMsg("[Derpibooru] { " + Derpibooru.errorcode + "Error: No images found. }");
				}
			}
		});
	}

}

// TODO add pages:all support
// Detect exact number of pages to grab by using a query like this:
// https://derpibooru.org/search.json?q=faved_by:Xaekai
// and using the "total" returned


Derpibooru.favorites = function(bot, username, data, hasPermission) {
//	var user = "fad4c7df6368726706dc0000";
	var user = {} // = "351604";
	var type = "favorites";
	var specified = false;

	Derpibooru.commandLock = true;
	if(data.match(/userid:\d+/)){
		user.id = data.match(/userid:(\d+)/)[1]
		data = data.replace(/userid:\d+/, "").trim()
		specified = "id";
	}
	else if (data.match(/user(?:name)?:\[[\w\d-_ ]+\]/)){
		user.name = data.match(/user(?:name)?:\[([\w\d-_ ]+)\]/)[1]
		data = data.replace(/user(?:name)?:\[[\w\d-_ ]+\]/, "").trim()
		specified = "name";
	}
	// Javascript doesn't support RegEx branch reset
	// copy paste job is more elegant than making some giant regex
	else if (data.match(/user(?:name)?:[\w\d-_]+/)){
		user.name = data.match(/user(?:name)?:([\w\d-_]+)/)[1]
		data = data.replace(/user(?:name)?:[\w\d-_]+/, "").trim()
		specified = "name";
	}

	if(!specified && !(Derpibooru.cachedStaging[type].length || Derpibooru.cachedReStaging[type].length)){
		Derpibooru.commandLock = false;
		return bot.sendChatMsg("[Derpibooru] { Error: You must specify a username or userid }");
	}

	if(!specified && !data.match(/cache/)){
		Derpibooru.commandLock = false;
		if(!Derpibooru.cachedStaging[type].length){
			Derpibooru.cachedStaging[type] = Derpibooru.cachedReStaging[type].slice(); Derpibooru.cachedReStaging[type].length = 0;
		}
		var item = Derpibooru.cachedStaging[type].splice(Math.floor(Math.random() * Derpibooru.cachedStaging[type].length), 1)[0];
		var image = "http:" + item.representations.medium ;
		Derpibooru.cachedReStaging[type].push(item)
		return bot.sendChatMsg("[Derpibooru] { User Favorites: " + Derpibooru.favesData.user.name + " } \n" + image + Derpibooru.embed);
	}




	request({ 
		url: String().concat("https://derpibooru.org/profiles/",user[specified],".json?key=",Derpibooru.apikey), 
		pool: Derpibooru.pool, 
		followRedirect: false 
	}, function(error, response, body){
		if(error){ 
			Derpibooru.commandLock = false;
			return bot.sendChatMsg("[Derpibooru] { Error: " + error + " }", true);
		}
		if(response.statusCode == 302){
			Derpibooru.commandLock = false;
			return bot.sendChatMsg("[Derpibooru] { Error: " + "User not found." + " }", true);
		}
		else{
			// {"id":351604,"name":"Xaekai","avatar":"//derpicdn.net/avatars/W1siZiIsIjIwMTMvMTIvMTEvMDZfMDNfMzhfMTk5X3BpY19tZWdhbG9kb25waXgyLmpwZyJdXQ","creation_date":"2013-12-11T03:51:24.667Z","comment_count":439,"uploads_count":111,"post_count":50,"topic_count":0}
			var userdata = JSON.parse(body);
			if(specified == "id" && user.id == userdata["name"]){
				Derpibooru.commandLock = false;
				return bot.sendChatMsg("[Derpibooru] { Error: Username/Userid Collision }")
			}

			if(data.match(/cache/)){
				if(!hasPermission){
					Derpibooru.commandLock = false;
					bot.sendChatMsg("[Derpibooru] { Error: Insufficient privileges. }");
					return // bot.sendChatMsg("/kick " + username);
				}
		
				Derpibooru.favesData.user = userdata
				bot.sendChatMsg("[Derpibooru] { Cache User Favorites: " + userdata.name + " }")
		
				var pages = Derpibooru.cacheParse(bot, data, type), waiting = pages, cache = [];
				for (var page = 0; page < pages; page++) {
					var url = String().concat("https://derpibooru.org/images/favourites.json?user_id=",userdata.id,"&key=",Derpibooru.apikey,"&page=",(page+1),"&perpage=50");
					request({ url: url, pool: Derpibooru.pool }, function(error, response, body){
						if(error){ 
							return bot.sendChatMsg("[Derpibooru] { Error: " + error + " }", true);
						} else {
							cache = cache.concat(JSON.parse(body).images)                       
						}
						if(--waiting == 0){
							return Derpibooru.finishCache(bot, cache, "favorites");
						}
					});
				};
			}
			else
			{
				var page = 1; //Math.floor(Math.random()*6)
				var url = String().concat("https://derpibooru.org/images/favourites.json?user_id=",userdata.id,"&key=",Derpibooru.apikey,"&page=",page,"&perpage=50");
				request({ url: url, pool: Derpibooru.pool }, function(error, response, body){
					Derpibooru.commandLock = false;
					if(error){ 
						return bot.sendChatMsg("[Derpibooru] { Error: " + error + " }", true);
					} else {
						var result = JSON.parse(body);
						result = result.images ; 
						if(result.length > 0){
							var index = Math.floor(Math.random()*result.length);
							var image = "https:" + result[index].representations.medium ;
							return bot.sendChatMsg("[Derpibooru] { User Favorites: " + userdata.name + " } \n" + image + Derpibooru.embed);
							}
						else {
							return bot.sendChatMsg("[Derpibooru] { User Favorites: " + userdata.name + " !!! " + Derpibooru.errorcode + "Error: No images found. }");
						}
					}
				});
			}
			//
		}
	});
}

module.exports = Derpibooru;