package de.yannicpunktdee.yoshibot.utils;

import de.yannicpunktdee.yoshibot.main.YoshiBot;
import lombok.NonNull;
import lombok.SneakyThrows;
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.exceptions.ErrorResponseException;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public abstract class StatusProviderFactory {
	
	public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss E, dd.MM.yyyy",
																					   Locale.GERMANY);
	private static final Map<StatusProvider, Long> providers = new HashMap<>();
	private static final Map<StatusProvider, JSONObject> providerJSON = new HashMap<>();
	private static JSONObject rootJSON;
	private static File configFile;
	
	@NonNull
	private static final TextChannel statusChannel =
			Objects.requireNonNull(YoshiBot.getInstance().getGuild().getTextChannelById(Resources.getStatus_channel()));
	
	@SneakyThrows
	public static void createStatusProviders(String configFilePath, Set<Provider> allProviders) {
		configFile = new File(configFilePath);
		rootJSON   = new JSONObject(String.join("\n", Files.readAllLines(configFile.toPath())));
		final JSONArray servers = rootJSON.getJSONArray("servers");
		for (int i = 0; i < servers.length(); i++) {
			final JSONObject server = servers.getJSONObject(i);
			final String ip = server.getString("ip");
			final String name = server.getString("name");
			
			if (!server.has("timestamp")) {
				server.put("timestamp", TIME_FORMATTER.format(LocalDateTime.now()));
			}
			final LocalDateTime timestamp = LocalDateTime.parse(server.getString("timestamp"), TIME_FORMATTER);
			
			if (!server.has("message")) {
				server.put("message", -1);
			}
			final long msg = ensureMessageId(server.getLong("message"));
			server.put("message", msg);
			
			StatusProvider provider = new StatusProvider(name, Resources.getStatusUpdate(), ip, timestamp);
			providers.put(provider, msg);
			providerJSON.put(provider, servers.getJSONObject(i));
		}
		
		allProviders.addAll(providers.keySet());
		writeJSON();
	}
	
	public static void updateStatus(StatusProvider provider, MessageEmbed msg) {
		statusChannel.editMessageById(providers.get(provider), msg).queue();
	}
	
	public static void updateTimestamp(StatusProvider provider, LocalDateTime timestamp) {
		providerJSON.get(provider).put("timestamp", TIME_FORMATTER.format(timestamp));
		writeJSON();
	}
	
	@SneakyThrows
	private static void writeJSON() {
		BufferedWriter bw = new BufferedWriter(new FileWriter(configFile));
		bw.write(rootJSON.toString(2));
		bw.flush();
	}
	
	private static long createStatusMessage() {
		Logger.logInfo("Creating new Status Message!");
		return StatusProviderFactory.statusChannel.sendMessage(
						new MessageBuilder()
								.append("ServerInformation")
								.build())
				.complete().getIdLong();
	}
	
	private static long ensureMessageId(long messageId) {
		try {
			Message msg = StatusProviderFactory.statusChannel.retrieveMessageById(messageId).complete();
			return msg.getIdLong();
		} catch (ErrorResponseException e) {
			return createStatusMessage();
		}
	}
}
