package me.despawningbone.discordbot.command.info;

import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import me.despawningbone.discordbot.utils.MiscUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.exceptions.PermissionException;

@SuppressWarnings("deprecation")
public class UrbanDictionary extends Command {
	public UrbanDictionary() {
		this.desc = "Ask the best dictionary in the world!";
		this.alias = Arrays.asList("urban", "ud", "u");
		this.usage = "<words> [|index]";
		this.examples = Arrays.asList("life", "life | 2");
	}

	@Override
	public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
		if (args.length < 1) {
			return new CommandResult(CommandResultType.INVALIDARGS, "You can't search nothing you dumbo :stuck_out_tongue:");
		}
		String search;
		String content = String.join(" ", args);
		JSONTokener result = null;
		// System.out.println(content); //debug
		boolean nonum = false;
		boolean error = false;
		int num = 0;
		try {
			try {
				num = Integer.valueOf(content.split(" \\| ")[1]);
			} catch (NumberFormatException e) {
				error = true;
			}
			if (num < 1 || error) {
				channel.sendMessage("Invalid number entered. The bot will default to the top definition.").queue();
				num = 0;
			} else {
				num = num - 1;
			}
		} catch (ArrayIndexOutOfBoundsException e) {
			nonum = true;
		}
		String ss = null;
		if (nonum) {
			ss = content;
		} else {
			ss = content.split(" \\| ", 2)[0];
		}
		try {
			search = URLEncoder.encode(ss, "UTF-8");
			try {
				InputStream input = new URL("http://api.urbandictionary.com/v0/define?term=" + search).openStream();
				result = new JSONTokener(new InputStreamReader(input, "UTF-8"));

			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		if(result == null) return new CommandResult(CommandResultType.FAILURE, "The service is not available right now!");
		JSONObject mainobj = new JSONObject(result);
		// System.out.println(mainobj.toString()); //debug
		JSONArray choice = mainobj.getJSONArray("list");
		if (choice.length() < 1) {
			return new CommandResult(CommandResultType.NORESULT);
		}
		// System.out.println(choice.toString()); //debug
		List<JSONObject> list = new ArrayList<JSONObject>();
		for (int i = 0; i < choice.length(); i++) {
			list.add(choice.getJSONObject(i));
		}
		Collections.sort(list, new Comparator<JSONObject>() {

			public int compare(JSONObject a, JSONObject b) {
				int valA = 0;
				int valB = 0;
				valA = a.getInt("thumbs_up") - a.getInt("thumbs_down");
				valB = b.getInt("thumbs_up") - b.getInt("thumbs_down");
				return Integer.compare(valB, valA);
			}
		});

		JSONArray sortedchoice = new JSONArray(list);
		JSONObject r;
		try {
			r = (JSONObject) sortedchoice.get(num);
		} catch (JSONException e) {
			channel.sendMessage("The number you've entered is too large. The bot will default to the top definition.")
					.queue();
			num = 0;
			r = (JSONObject) sortedchoice.get(num);
		}
		// JSONObject r = (JSONObject) choice.get(num);
		String def = StringEscapeUtils.unescapeJava(r.getString("definition"));
		String tlink = StringEscapeUtils.unescapeJava(r.getString("permalink"));
		String eg = StringEscapeUtils.unescapeJava(r.getString("example"));
		String word = StringEscapeUtils.unescapeJava(r.getString("word"));
		String a = StringEscapeUtils.unescapeJava(r.getString("author"));
		BigInteger tu = r.getBigInteger("thumbs_up");
		BigInteger td = r.getBigInteger("thumbs_down");
		// String link = tlink.split("/", 4)[0] + "/" + tlink.split("/", 4)[1] +
		// "/" + tlink.split("/", 4)[2] + "/";
		EmbedBuilder e = new EmbedBuilder();
		if (num == 0) {
			e.setAuthor(word + " (Top definition)\n\n", tlink, null);
		} else {
			e.setAuthor(word + " (" + MiscUtils.ordinal(num + 1) + " definition)\n", tlink, null);
		}
		// e.setThumbnail("https://is4-ssl.mzstatic.com/image/thumb/Purple71/v4/71/5a/45/715a450b-b0af-0912-c0a6-208fd92b559b/source/256x256bb.jpg");
		e.setColor(new Color(0, 0, 255));
		try {
			e.setDescription(def);
			//e.addField("\nDefinition", def, false);
			if (!eg.isEmpty()) {
				e.addField("Example:", "```" + eg + "```", false);
			}
			e.addField("👍 ", String.valueOf(tu), true);
			e.addField("👎", String.valueOf(td), true);
			e.setFooter("Author: " + a, null);
			MessageEmbed em = e.build();
			channel.sendMessage(em).queue();
		} catch (PermissionException | IllegalArgumentException e1) {   //this shouldnt happen anymore, since description limit is the same as a normal message
			MessageBuilder smsg = new MessageBuilder();
			if (num == 0) {
				smsg.append("**" + word + "** (Top definition)\n\n");
			} else {
				smsg.append("**" + word + "** (" + MiscUtils.ordinal(num + 1) + " definition)\n\n");
			}
			smsg.append(def);
			if (!eg.isEmpty()) {
				smsg.append("```\n" + eg + "```\n");
			} else {
				smsg.append("\n\n");
			}
			smsg.append("<" + tlink + ">\n\n");
			smsg.append("Author: `" + a + "`\n");
			smsg.append("👍 " + tu + "                    👎 " + td);
			Message fmsg = null;
			try {
				fmsg = smsg.build();
			} catch (IllegalStateException e2) {
				return new CommandResult(CommandResultType.TOOLONG);
			}
			channel.sendMessage(fmsg).queue();
		}
		return new CommandResult(CommandResultType.SUCCESS);
	}

}
