package me.despawningbone.discordbot.command.anime;

import java.awt.Color;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.jsoup.Connection.Response;
import org.jsoup.Jsoup;

import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;

public class Waifu extends Command {
	public Waifu() {
		this.desc = "Find information about your waifu!"; //, or leave it blank for a random one!";
		this.usage = "<name> [| index]";
		this.examples = Arrays.asList("neptune", "ryuZU");
	}

	@Override
	public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
		channel.sendTyping().queue();
		String[] stripped = String.join(" ", args).split("\\|");
		/*		, url = "";
		if (args.length < 1) {
			url = "https://mywaifulist.moe/random/";
		} else {
			url = "https://mywaifulist.moe/waifu/" + stripped.replaceAll(" ", "-");
		}
		JSONObject main = getWaifuJSON(url);
		if (main == null) {
			String search;
			int index;
			if (stripped.contains("|")) {
				String[] split = stripped.split(" \\|");
				search = split[0];
				try {
					index = Integer.parseInt(split[1].trim()) - 1;
				} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
					channel.sendMessage("Invalid index inputted. Defaulting to first result.").queue();
					channel.sendTyping().queue();
					index = 0;
				}
			} else {
				search = stripped;
				index = 0;
			}
			try {
				url = GoogleSearch
						.search(URLEncoder.encode("site:https://mywaifulist.moe/waifu " + search, "UTF-8"), 20)
						.get(index).getValue();
				// System.out.println(url); //debug
			} catch (IOException | IndexOutOfBoundsException e) {
				if (e instanceof IndexOutOfBoundsException) {
					return new CommandResult(CommandResultType.NORESULT);
				} else {
					return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
				}
			}
			main = getWaifuJSON(url);
		}*/
		
		if(args.length < 1) return new CommandResult(CommandResultType.FAILURE, "Please enter something to search for!");
		JSONObject main;
		try {
			Response con = Jsoup.connect("https://mywaifulist.moe/dash/").execute();
            String cookie = String.join(";", con.header("Set-Cookie").split("; expires.*?,.*?,")).split("; expires")[0];
            String csrf = con.parse().selectFirst("meta[name=\"csrf-token\"]").attr("content");
			String res = Jsoup.connect("https://mywaifulist.moe/api/waifu/search")
					.userAgent("Mozilla/4.0")
					.header("Cookie", cookie)
					.header("X-CSRF-Token", csrf)
					.header("X-Requested-With", "XMLHttpRequest")
					.followRedirects(true)
					.requestBody("{\"query\":\"" + stripped[0].trim() + "\"}").post().text();
			int index = 0;
			JSONArray jarr = new JSONArray(new JSONTokener(res));
			try {
				 //System.out.println(arr.length());
				 if(stripped.length > 1) index = Integer.parseInt(stripped[1].trim()) - 1;	
				 if(jarr.length() <= index && index != 0) throw new NumberFormatException();
			} catch (NumberFormatException e) {
				channel.sendMessage("Invalid index inputted. Defaulting to first result.").queue();
				channel.sendTyping().queue();
				index = 0;
			}
			List<JSONObject> arr = new ArrayList<>();
			for(Object obj : jarr) arr.add((JSONObject) obj);
			arr = arr.stream().filter(o -> !o.getString("type").equalsIgnoreCase("series")).sorted((a, b) -> Integer.compare((b.has("likes") ? b.getInt("likes") : 0) + (b.has("trash") ? b.getInt("trash") : 0), (a.has("likes") ? a.getInt("likes") : 0) + (a.has("trash") ? a.getInt("trash") : 0))).collect(Collectors.toList());  //sort by popularity since the search result sucks ass
			main = new JSONObject(new JSONTokener(Jsoup.connect("https://mywaifulist.moe/api/waifu/" + arr.get(index).getInt("id"))
					.userAgent("Mozilla/4.0")
					.header("Cookie", cookie)
					.header("X-CSRF-Token", csrf)
					.header("X-Requested-With", "XMLHttpRequest")
					.followRedirects(true).ignoreContentType(true).get().text())).getJSONObject("data");
			System.out.println(main);
		} catch (IndexOutOfBoundsException e) {
			//e.printStackTrace();
			return new CommandResult(CommandResultType.NORESULT);
		} catch (IOException e) {
			return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
		}
		EmbedBuilder em = new EmbedBuilder();
		em.setColor(new Color(44, 62, 80));
		em.setTitle((main.getBoolean("husbando") ? "Husbando" : "Waifu") + " info of " + main.getString("name"), "https://mywaifulist.moe/waifu/" + main.getString("slug"));
		
		JSONObject series = main.getJSONObject("series");
		em.setAuthor("Series: " + series.getString("name"), "https://mywaifulist.moe/series/" + series.getString("slug"));
		if(!main.getJSONObject("series").getString("display_picture").isEmpty()) em.setThumbnail(main.getJSONObject("series").getString("display_picture"));
		try {
			em.setDescription(main.getString("description").substring(0, Math.min(main.getString("description").length(), 2040)) + (main.getString("description").length() > 2040 ? "..." : "")); 
		} catch (IllegalArgumentException e) {
			return new CommandResult(CommandResultType.TOOLONG);
		}
		
		em.setImage(main.getString("display_picture").replaceAll("\\\\", ""));
		
		ArrayList<JSONObject> appearances = new ArrayList<>();
		int totalName = 0;
		for(Object obj : main.getJSONArray("appearances")) {
			JSONObject jobj = ((JSONObject) obj);
			appearances.add(jobj);
			totalName += jobj.getString("name").length() + jobj.getString("slug").length() + 43;
		}
		final int avg = (1024 - totalName) / appearances.size();
		System.out.println(appearances.stream().map(jobj -> "[" + jobj.getString("name") + "](https://mywaifulist.moe/series/" + jobj.getString("slug") + " \"" + jobj.getString("description").substring(0, Math.min(jobj.getString("description").length(), avg)) + (jobj.getString("description").length() > avg ? "..." : "").replaceAll("\"", "”") + "\")").collect(Collectors.joining(", ")).length());
		em.addField("Appearances", appearances.stream().map(jobj -> "[" + jobj.getString("name") + "](https://mywaifulist.moe/series/" + jobj.getString("slug") + " \"" + jobj.getString("description").substring(0, Math.min(jobj.getString("description").length(), avg)) + (jobj.getString("description").length() > avg ? "..." : "").replaceAll("\"", "”") + "\")").collect(Collectors.joining(", ")), false);
		
		if(!main.getString("original_name").isEmpty()) em.addField("Also known as", main.getString("original_name") + (main.isNull("romaji_name") ? "" : ", " + main.getString("romaji_name")), false);
		
		em.addBlankField(false);
		
		if (!main.getString("origin").equals("")) {
			em.addField("Origin", main.getString("origin"), true);
		}
		if (main.getDouble("height") != 0.00) {
			em.addField("Height", String.valueOf(main.getDouble("height")), true);
		}
		if (main.getDouble("weight") != 0.00) {
			em.addField("Weight", String.valueOf(main.getDouble("weight")), true);
		}
		if (main.getDouble("bust") != 0.00) {
			em.addField("Bust", String.valueOf(main.getDouble("bust")), true);
		}
		if (main.getDouble("hip") != 0.00) {
			em.addField("Hip", String.valueOf(main.getDouble("hip")), true);
		}
		if (main.getDouble("waist") != 0.00) {
			em.addField("Waist", String.valueOf(main.getDouble("waist")), true);
		}
		if (!main.getString("blood_type").isEmpty()) {
			em.addField("Blood type", main.getString("blood_type"), true);
		}
		if (!main.isNull("birthday_day") && !main.getString("birthday_month").isEmpty()) {
			em.addField("Birthday",
					main.getString("birthday_month") + " " + String.valueOf(main.getInt("birthday_day"))
							+ ( main.isNull("birthday_year") || main.getString("birthday_year").isEmpty() ? "" : ", " + main.getString("birthday_year")),
					true);
		}
		
		if (em.getFields().size() == 5) {
			em.addBlankField(true);
		}
		
		String tags = main.getJSONArray("tags").toList().stream().map(o -> o.toString().replaceAll("\\{name=", "").replaceAll(", id=.*\\}", "")).collect(Collectors.joining(", "));	
		if(!tags.isEmpty()) em.addField("Tags", tags, false);
		
		if(em.getFields().size() > 2) em.addBlankField(false);
		em.addField("Likes", main.getInt("likes") + " (#" + (main.isNull("like_rank") ? "N/A" : main.getInt("like_rank")) + ")", true);
		em.addField("Popularity rank", "#" + (main.isNull("popularity_rank") ? "N/A" : main.getInt("popularity_rank")), true);
		em.addField("Trash", main.getInt("trash") + " (#" + (main.isNull("trash_rank") ? "N/A" : main.getInt("trash_rank")) + ")", true);
		
		em.setFooter("Created by " + main.getJSONObject("creator").getString("name") + /*", Last updated: "
				+ main.getString("updated_at") +*/ " | MyWaifuList.moe", null);
		channel.sendMessage(em.build()).queue();
		return new CommandResult(CommandResultType.SUCCESS);
	}
}
