package land.chipmunk.chipmunkmod.modules;

import com.google.common.hash.Hashing;
import land.chipmunk.chipmunkmod.ChipmunkMod;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;

import java.nio.charset.StandardCharsets;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Pattern;

public class CustomChat {
    private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();

    // https://github.com/kaboomserver/extras/blob/master/src/main/java/pw/kaboom/extras/modules/player/PlayerChat.java#L49C9-L81C26
    private static final TextReplacementConfig URL_REPLACEMENT_CONFIG =
            TextReplacementConfig
                    .builder()
                    .match(Pattern
                            .compile("((https?://(ww(w|\\d)\\.)?|ww(w|\\d))[-a-zA-Z0-9@:%._+~#=]{1,256}"
                                    + "\\.[a-zA-Z0-9]{2,6}\\b([-a-zA-Z0-9@:%_+.~#?&/=]*))"))
                    .replacement((b, c) -> {
                        if (c == null) {
                            return null;
                        }

                        if (b.groupCount() < 1) {
                            return null;
                        }

                        final String content = b.group(1);
                        final String url;

                    /*
                        Minecraft doesn't accept "www.google.com" as a URL
                        in click events
                     */
                        if (content.contains("://")) {
                            url = content;
                        } else {
                            url = "https://" + content;
                        }

                        return Component.text(content, NamedTextColor.BLUE)
                                .decorate(TextDecoration.UNDERLINED)
                                .clickEvent(ClickEvent.openUrl(url));
                    })
                    .build();

    private final MinecraftClient client;

    public static final CustomChat INSTANCE = new CustomChat(MinecraftClient.getInstance());

    public boolean enabled = true;

    public String format;

    private Timer timer;

    private int total = 0;

    public CustomChat (MinecraftClient client) {
        this.client = client;

        reloadFormat();
    }

    public void init () {
        final TimerTask task = new TimerTask() {
            public void run () {
                tick();
            }
        };

        resetTotal();

        timer = new Timer();
        timer.schedule(task, 0, 50);
    }

    private void tick () {
        final ClientPlayNetworkHandler networkHandler = client.getNetworkHandler();

        if (networkHandler != null) return;

        resetTotal();
        cleanup();
    }

    public void resetTotal() {
        total = 0;
    }

    private void cleanup () {
        if (timer == null) return;

        timer.cancel();
        timer.purge();
    }

    public void reloadFormat () {
       this.format = GSON.serializeToTree(ChipmunkMod.CONFIG.customChat.format).toString();
    }

    public void chat (String message) {
        final ClientPlayerEntity player = client.player;

        if (player == null) return;

        if (!enabled || !player.hasPermissionLevel(2) || !player.isCreative()) {
            Chat.sendChatMessage(message, true);
            return;
        }

        final String username = MinecraftClient.getInstance().getSession().getUsername();

        final String sanitizedMessage = message
                .replace("\\", "\\\\")
                .replace("\"", "\\\"");

        final String randomized = String.valueOf(Math.random());

        final LegacyComponentSerializer serializer = LegacyComponentSerializer.legacyAmpersand();

        final Component messageWithColors = serializer.deserialize(message);
        final Component completeMessage = messageWithColors.replaceText(URL_REPLACEMENT_CONFIG);

        final String stringMessage = GSON.serialize(completeMessage).replace("MESSAGE", randomized);

        final String key = ChipmunkMod.CONFIG.bots.chomens.formatKey;

        final String hash = key != null ?
                Hashing.sha256()
                    .hashString(key + total, StandardCharsets.UTF_8)
                    .toString()
                    .substring(0, 8) :
                "";

        total++;

        try {
//            final MutablePlayerListEntry entry = Players.INSTANCE.getEntry(client.getNetworkHandler().getProfile().getId());

//            final Component displayNameComponent = entry.displayName().asComponent();

//            final String prefix = GsonComponentSerializer.gson().serialize(Component.join(JoinConfiguration.separator(Component.empty()), displayNameComponent.children().get(0)));
//            final String displayName = GsonComponentSerializer.gson().serialize(Component.join(JoinConfiguration.separator(Component.empty()), displayNameComponent.children().get(1)));

            // TODO: make this code not ohio code.,.,
            String sanitizedFormat = format
//                        .replace("\"PREFIX\"", prefix)
//                        .replace("\"DISPLAYNAME\"", displayName)
                            .replace("USERNAME", username)
                            .replace("UUID", player.getUuidAsString())
                            .replace("HASH", hash)
                            .replace("\"extra\":[\"MESSAGE\"]", "\"extra\":[" + stringMessage + "]")
                            .replace("MESSAGE", sanitizedMessage)
                            .replace(randomized, "MESSAGE"); // ohio ohio

            CommandCore.INSTANCE.run((KaboomCheck.INSTANCE.isKaboom ? "minecraft:tellraw @a " : "tellraw @a ") + sanitizedFormat);
        } catch (Exception e) {
            if (client.player == null) return;
            client.player.sendMessage(Component.text(e.toString()).color(NamedTextColor.RED));
        }
    }
}
