package ru.fiw.proxyserver;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.TitleScreen;
import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.gui.widget.CheckboxWidget;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.TextWidget;
import net.minecraft.client.input.KeyInput;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import org.apache.commons.lang3.StringUtils;

public class GuiProxy extends Screen {
    private boolean isSocks4 = false;

    private TextFieldWidget ipPort;
    private TextFieldWidget username;
    private TextFieldWidget password;
    private CheckboxWidget enabledCheck;

    private Screen parentScreen;

    private String msg = "";

    private int[] positionY;
    private int positionX;

    private TestPing testPing = new TestPing();

    private TextWidget authFieldLabel;
    private TextWidget passwordFieldLabel;
    private TextWidget msgLabel;

    private static String text_proxy = Text.translatable("ui.proxyserver.options.proxy").getString();

    public GuiProxy(Screen parentScreen) {
        super(Text.literal(text_proxy));
        this.parentScreen = parentScreen;
    }

    private static boolean isValidIpPort(String ipP) {
        String[] split = ipP.split(":");
        if (split.length > 1) {
            if (!StringUtils.isNumeric(split[1])) return false;
            int port = Integer.parseInt(split[1]);
            if (port < 0 || port > 0xFFFF) return false;
            return true;
        } else {
            return false;
        }
    }

    private boolean checkProxy() {
        if (!isValidIpPort(ipPort.getText())) {
            msg = Formatting.RED + Text.translatable("ui.proxyserver.options.invalidIpPort").getString();
            this.ipPort.setFocused(true);
            return false;
        }
        return true;
    }

    private void centerButtons(int amount, int buttonLength, int gap) {
        positionX = (this.width / 2) - (buttonLength / 2);
        positionY = new int[amount];
        int center = (this.height + amount * gap) / 2;
        int buttonStarts = center - (amount * gap);
        for (int i = 0; i != amount; i++) {
            positionY[i] = buttonStarts + (gap * i);
        }
    }

    @Override
    public boolean keyPressed(KeyInput input) {
        super.keyPressed(input);
        msg = "";
        testPing.state = "";
        return true;
    }

    @Override
    public void render(DrawContext context, int mouseX, int mouseY, float partialTicks) {
        super.render(context, mouseX, mouseY, partialTicks);
        msgLabel.setMessage(Text.literal(!msg.isEmpty() ? msg : testPing.state));
    }

    @Override
    public void tick() {
        testPing.pingPendingNetworks();
    }

    @Override
    public void init() {
        int buttonLength = 160;
        centerButtons(10, buttonLength, 26);

        isSocks4 = ProxyServer.proxy.type == Proxy.ProxyType.SOCKS4;

        // Row 1: proxy type label + button
        this.addDrawableChild(new TextWidget(positionX, positionY[1] + 5,
                Text.translatable("ui.proxyserver.options.proxyType"), this.textRenderer));
        ButtonWidget proxyType = ButtonWidget.builder(Text.literal(isSocks4 ? "Socks 4" : "Socks 5"), button -> {
            isSocks4 = !isSocks4;
            button.setMessage(Text.literal(isSocks4 ? "Socks 4" : "Socks 5"));
            authFieldLabel.setMessage(Text.translatable(isSocks4 ? "ui.proxyserver.auth.id" : "ui.proxyserver.auth.username"));
            passwordFieldLabel.setMessage(isSocks4 ? Text.empty() : Text.translatable("ui.proxyserver.auth.password"));
        }).dimensions(positionX, positionY[1], buttonLength, 20).build();
        this.addDrawableChild(proxyType);

        // Row 2: IP:Port label + field
        this.addDrawableChild(new TextWidget(positionX, positionY[2] + 5,
                Text.translatable("ui.proxyserver.options.ipPort"), this.textRenderer));
        this.ipPort = new TextFieldWidget(this.textRenderer, positionX, positionY[2], buttonLength, 20, Text.literal(""));
        this.ipPort.setText(ProxyServer.proxy.ipPort);
        this.ipPort.setMaxLength(1024);
        this.ipPort.setFocused(true);
        this.addDrawableChild(this.ipPort);

        // Row 3: auth header
        int authHeaderX = this.width / 2 - this.textRenderer.getWidth(Text.translatable("ui.proxyserver.options.auth")) / 2;
        this.addDrawableChild(new TextWidget(authHeaderX, positionY[3] + 8,
                Text.translatable("ui.proxyserver.options.auth"), this.textRenderer));

        // Row 4: auth field label + username field
        authFieldLabel = new TextWidget(positionX, positionY[4] + 5,
                Text.translatable(isSocks4 ? "ui.proxyserver.auth.id" : "ui.proxyserver.auth.username"), this.textRenderer);
        this.addDrawableChild(authFieldLabel);
        this.username = new TextFieldWidget(this.textRenderer, positionX, positionY[4], buttonLength, 20, Text.literal(""));
        this.username.setMaxLength(255);
        this.username.setText(ProxyServer.proxy.username);
        this.addDrawableChild(this.username);

        // Row 5: password label + field (hidden for socks4)
        passwordFieldLabel = new TextWidget(positionX, positionY[5] + 5,
                isSocks4 ? Text.empty() : Text.translatable("ui.proxyserver.auth.password"), this.textRenderer);
        this.addDrawableChild(passwordFieldLabel);
        this.password = new TextFieldWidget(this.textRenderer, positionX, positionY[5], buttonLength, 20, Text.literal(""));
        this.password.setMaxLength(255);
        this.password.setText(ProxyServer.proxy.password);
        this.addDrawableChild(this.password);

        // Row 6: status message
        msgLabel = new TextWidget(this.width / 2 - 100, positionY[6] + 5, Text.empty(), this.textRenderer);
        this.addDrawableChild(msgLabel);

        // Row 7: enable checkbox
        int posXButtons = (this.width / 2) - (((buttonLength / 2) * 3) / 2);
        CheckboxWidget.Builder checkboxBuilder = CheckboxWidget.builder(Text.translatable("ui.proxyserver.options.proxyEnabled"), this.textRenderer);
        checkboxBuilder.pos((this.width / 2) - (15 + textRenderer.getWidth(Text.translatable("ui.proxyserver.options.proxyEnabled"))) / 2, positionY[7]);
        if (ProxyServer.proxyEnabled) {
            checkboxBuilder.checked(ProxyServer.proxyEnabled);
        }
        this.enabledCheck = checkboxBuilder.build();
        this.addDrawableChild(this.enabledCheck);

        // Row 8: apply / test / cancel buttons
        ButtonWidget apply = ButtonWidget.builder(Text.translatable("ui.proxyserver.options.apply"), button -> {
            if (checkProxy()) {
                ProxyServer.proxy = new Proxy(isSocks4, ipPort.getText(), username.getText(), password.getText());
                ProxyServer.proxyEnabled = enabledCheck.isChecked();
                Config.setDefaultProxy(ProxyServer.proxy);
                Config.saveConfig();
                MinecraftClient.getInstance().setScreen(new MultiplayerScreen(new TitleScreen()));
            }
        }).dimensions(posXButtons, positionY[8], buttonLength / 2 - 3, 20).build();
        this.addDrawableChild(apply);

        ButtonWidget test = ButtonWidget.builder(Text.translatable("ui.proxyserver.options.test"), (button) -> {
            if (ipPort.getText().isEmpty() || ipPort.getText().equalsIgnoreCase("none")) {
                msg = Formatting.RED + Text.translatable("ui.proxyserver.err.specProxy").getString();
                return;
            }
            if (checkProxy()) {
                testPing = new TestPing();
                testPing.run("mc.hypixel.net", 25565, new Proxy(isSocks4, ipPort.getText(), username.getText(), password.getText()));
            }
        }).dimensions(posXButtons + buttonLength / 2 + 3, positionY[8], buttonLength / 2 - 3, 20).build();
        this.addDrawableChild(test);

        ButtonWidget cancel = ButtonWidget.builder(Text.translatable("ui.proxyserver.options.cancel"), (button) -> {
            MinecraftClient.getInstance().setScreen(parentScreen);
        }).dimensions(posXButtons + (buttonLength / 2 + 3) * 2, positionY[8], buttonLength / 2 - 3, 20).build();
        this.addDrawableChild(cancel);
    }

    @Override
    public void close() {
        msg = "";
    }
}
