package me.despawningbone.discordbot.command.anime;

import java.awt.Color;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import me.despawningbone.discordbot.DiscordBot;
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.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;

public class Anime extends Command {

	private static byte[] encodedMalAuth = Base64.encodeBase64((DiscordBot.tokens.getProperty("mal")).getBytes(StandardCharsets.UTF_8));
	public static String malAuth = "Basic " + new String(encodedMalAuth);
	
	public Anime() {
		this.desc = "Find information for any anime!";
		this.usage = "<name> [| index]";
		this.examples = Arrays.asList("clockwork planet", "chuunibyou | 2");
	}
	
	@Override
	public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
		if(args.length < 1) {
			return new CommandResult(CommandResultType.INVALIDARGS, "Please enter an anime title.");
		}
		channel.sendTyping().queue();
		
		String[] split = String.join(" ", args).split(" \\|");
		String search = split[0]; int index = 0;
		try {
			if(split.length > 1) {
				index = Integer.parseInt(split[1].trim()) - 1;	
				if(index < 1 || index > 10) throw new NumberFormatException();
			}
		} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
			channel.sendMessage("Invalid index inputted. Defaulting to first result...").queue();
		}
		
		JSONObject anime, info;
		
		try {
			JSONObject main = new JSONObject(new JSONTokener(new URL("https://api.jikan.moe/v3/search/anime?q=" + URLEncoder.encode(search, "UTF-8")).openStream()));			
			anime = main.getJSONArray("results").getJSONObject(index);
			info = new JSONObject(new JSONTokener(new URL("https://api.jikan.moe/v3/anime/" + anime.getInt("mal_id")).openStream()));
		} catch (IOException e) {
			return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
		} catch (JSONException e) {
			e.printStackTrace();
			return new CommandResult(CommandResultType.INVALIDARGS, "There are not enough results for your specified index!");
		}

		EmbedBuilder em = new EmbedBuilder();
		em.setTitle("Anime info for " + anime.getString("title") + " (" + anime.getString("type") + ")", anime.getString("url"));
		em.setThumbnail(anime.getString("image_url"));
		em.setDescription("JP: " + info.getString("title_japanese") + "\n\n" + (info.isNull("synopsis") ? "No synopsis information has been added to this title." : info.getString("synopsis")));
		
		em.addField("Episodes", (anime.getInt("episodes") == 0 ? "Unknown" : String.valueOf(anime.getInt("episodes"))), true);
		em.addField("Rating", anime.getDouble("score") == 0.0 ? "N/A" : String.valueOf(anime.getDouble("score")), true);
		em.addField("Airing status", info.getString("status"), true); 
		
		String[] aired = info.getJSONObject("aired").getString("string").split("to");
		em.addField("Premier season", info.isNull("premiered") ? "Unknown" : info.getString("premiered"), true);
		em.addField("Start date", aired[0], true);
		em.addField("End date", aired.length > 1 ? aired[1] : aired[0], true); 
		
		ArrayList<String> studios = new ArrayList<String>();
		for(Object genre : info.getJSONArray("studios")) studios.add("[" + ((JSONObject) genre).getString("name") + "](" + ((JSONObject) genre).getString("url") + ")");	
		String source = info.getJSONObject("related").has("Adaptation") ?
				"[" + info.getString("source") + "](" + info.getJSONObject("related").getJSONArray("Adaptation").getJSONObject(0).getString("url") + ")" : info.getString("source");
		if(!source.contains("[Light novel]") && !source.contains("anga]")) source = source.replaceFirst("\\[(.*?)\\](.*)", "$1 ([Adaptation]$2)");   //something couldve adapted it if its original instead
		
		em.addField("Studios", String.join(", ", studios), true);
		em.addField("PG rating", info.getString("rating"), true);
		em.addField("Source", source, true);
		
		ArrayList<String> genres = new ArrayList<String>();
		for(Object genre : info.getJSONArray("genres")) genres.add(((JSONObject) genre).getString("name"));
		em.addField("Genre", String.join(", ", genres), false);
		
		em.setFooter(MiscUtils.ordinal(index + 1) + " result - Rank #" + (info.isNull("rank") ? "N/A" : info.getInt("rank")) + ", Popularity #" + (info.isNull("popularity") ? "N/A" : info.getInt("popularity")) + " | MyAnimeList.net", "https://cdn.myanimelist.net/img/sp/icon/apple-touch-icon-256.png");
		em.setColor(new Color(46, 81, 162));
		channel.sendMessageEmbeds(em.build()).queue();
		return new CommandResult(CommandResultType.SUCCESS);
	}
	
}
