package me.despawningbone.discordbot.command.info;

import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.time.Instant;
import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
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 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 Fandom extends Command {
	public Fandom() {
		this.desc = "Search across all the fan-made wikis!";
		this.alias = Arrays.asList("wikia");
		this.usage = "<wiki name>: <search> [| index]";
		this.examples = Arrays.asList("zelda: gate of time", "clockwork planet: ryuZU", "angel beats: kanade");
	}

	@Override  //query for details using future too? since i already have to make 2 queries, making 3 in parallel wont make it much slower; the only concern is rate limit  //already doing sequential 3 queries, aint too slow so its fine
	public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
		channel.sendTyping().queue();
		//OffsetDateTime timesent = OffsetDateTime.now();

		/*for(TextChannel c : channel.getGuild().getTextChannels()) {  wtf is this
			try {
				System.out.println(c);
				Message m = c.getMessageById("607977540690378753").complete();
				if(m != null) channel.sendMessage(m.toString()).queue();
			} catch(ErrorResponseException | InsufficientPermissionException e) {
				e.printStackTrace();
				continue;
			}
			
		}*/
		
		if (args.length < 1) {
			return new CommandResult(CommandResultType.INVALIDARGS, "Invalid input, check help for more info.");
		}
		try {
			String[] init = String.join(" ", args).split(":");
			if(init.length < 2) {
				return new CommandResult(CommandResultType.INVALIDARGS, "Please use a colon to seperate the wiki and the search query!");
			}
			String[] split = init[1].split(" \\| ");
			String sword = split[0];
			int num = 0;
			if (split.length > 1) {
				try {
					num = Integer.parseInt(split[1]) - 1;
					if(num < 0) throw new NumberFormatException();
				} catch (NumberFormatException e) {
					channel.sendMessage("Invalid index inputted. Defaulting to the first result...").queue();
					num = 0;
				}
			}
			JSONTokener result = null;
			InputStream stream = null;
			String search = URLEncoder.encode(sword.trim(), "UTF-8");
			HttpURLConnection url = null;
			String wiki = init[0].replaceAll("[^\\p{L}\\p{N} ]+", "").replaceAll(" ", "-").toLowerCase();
			//boolean old = false;
			try {
				/*url = (HttpURLConnection) new URL("https://" + wiki + ".fandom.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection();
				stream = url.getInputStream();
				if(url.getResponseCode() == 302) {  //wikia is deprecated, for the few weeks of deprecation period only
					old = true;
					url = (HttpURLConnection) new URL("https://" + init[0].replaceAll("[^\\p{L}\\p{N} ]+", "").replaceAll(" ", "-").toLowerCase() + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection();
					stream = url.getInputStream();
					if(url.getResponseCode() == 302) {
						channel.sendMessage("Unknown wiki name!").queue();
						return new CommandResult(CommandResultType.NORESULT);
					}
				}*/
				//i can use this instead of the above code since wikia redirects with 301 with no exceptions; when everything finishes moving, i might have to change it to fandom though
				System.out.println("https://" + wiki + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14");
				url = (HttpURLConnection) new URL("https://" + wiki + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection();
				stream = url.getInputStream();
				if(url.getURL().toString().startsWith("https://community.fandom.com/")) {
					return new CommandResult(CommandResultType.FAILURE, "Unknown wiki name!");
				}
			} catch (IOException e) {
				if(url.getResponseCode() == 404) {
					return new CommandResult(CommandResultType.NORESULT, "it in the " + init[0] + " wiki");
				}
				return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
			}
			JSONObject item;
			try {
				result = new JSONTokener(stream);
				JSONArray main = new JSONObject(result).getJSONArray("items");
				item = main.getJSONObject(num);	
			} catch(JSONException e) {
				return new CommandResult(CommandResultType.NORESULT, "it in the " + init[0] + " wiki");
			}
			// System.out.println(i);
			//JSONArray array = new JSONObject(new JSONTokener(new URL("https://" + wiki + (old ? ".wikia" : ".fandom") + ".com/api/v1/Articles/AsSimpleJson?id=" + item.getInt("id")).openStream())).getJSONArray("sections").getJSONObject(0).getJSONArray("content");
			JSONArray array = new JSONObject(new JSONTokener(new URL("https://" + wiki + ".wikia.com/api/v1/Articles/AsSimpleJson?id=" + item.getInt("id")).openStream())).getJSONArray("sections").getJSONObject(0).getJSONArray("content");
			String desc = "";
			for(int i = 0; i < array.length(); i++) {
				desc = array.getJSONObject(i).getString("text");
				if(desc.contains("may refer to")) {
					JSONArray list = array.getJSONObject(i + 1).getJSONArray("elements");
					for(int j = 0; j < list.length(); j++) {
						desc += "\n- " + list.getJSONObject(j).getString("text");
					}
				}
				if(!desc.trim().replaceAll("(^\\h*)|(\\h*$)","").isEmpty()) {
					break;
				}
			}
			JSONObject details = new JSONObject(new JSONTokener(new URL("https://" + wiki + ".wikia.com/api/v1/Articles/Details?ids=" + item.getInt("id")).openStream()));
			JSONObject info = details.getJSONObject("items").getJSONObject(String.valueOf(item.getInt("id")));  //TODO make async
			EmbedBuilder eb = new EmbedBuilder();
			eb.setTitle(info.getString("title"), item.getString("url"));
			eb.setAuthor(StringUtils.capitalize(init[0]) + " wiki", details.getString("basepath"));
			eb.setDescription(desc);
			if(info.has("comments")) eb.addField("Comments", String.valueOf(info.getInt("comments")), false);
			if(!info.isNull("thumbnail")) eb.setThumbnail(info.getString("thumbnail"));
			eb.setFooter("Last edited by " + info.getJSONObject("revision").getString("user"), null);
			eb.setTimestamp(Instant.ofEpochSecond(Long.parseLong(info.getJSONObject("revision").getString("timestamp"))));
			eb.setColor(new Color(0, 42, 50));
			channel.sendMessage(eb.build()).queue();
			/*MessageBuilder smsg = new MessageBuilder();
			smsg.append("**" + item.getString("title") + "**\n\n");
			smsg.append(desc + "\n");
			smsg.append("<" + item.getString("url") + ">");
			OffsetDateTime timeReceived = OffsetDateTime.now();
			long ms = Math.abs(timesent.until(timeReceived, ChronoUnit.MILLIS));
			smsg.append("\n" + ms + "ms");
			Message fmsg = smsg.build();
			channel.sendMessage(fmsg).queue();*/
			return new CommandResult(CommandResultType.SUCCESS);   //add searched result name?
		} catch (Exception e) {
			return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
		}
	}
}
