package wtf.sten.vault;

import com.mojang.blaze3d.platform.InputConstants;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper;
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
import net.fabricmc.fabric.api.client.screen.v1.Screens;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.screens.PauseScreen;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.network.chat.Component;
import wtf.sten.vault.ui.GlassButton;
import wtf.sten.vault.ui.VaultScreen;

public final class StenVaultClient implements ClientModInitializer {
	private static KeyMapping openKey;
	private static int ticks;
	private static boolean openedLaunch;

	@Override
	public void onInitializeClient() {
		VaultConfig.get();
		StenNet.session = SessionStore.load();
		StenNet.bootstrap();
		openKey = KeyMappingHelper.registerKeyMapping(new KeyMapping(
			"key.sten-vault.open",
			InputConstants.Type.KEYSYM,
			InputConstants.KEY_V,
			KeyMapping.Category.MISC
		));
		ClientTickEvents.END_CLIENT_TICK.register(client -> {
			try {
				Remote.tick(client);
				ticks++;
				if (ticks % StenVault.HEARTBEAT_TICKS == 0) StenNet.heartbeat();
				else if (ticks % StenVault.POLL_TICKS == 0) StenNet.poll();
				VaultConfig cfg = VaultConfig.get();
				int shotEvery = Math.max(200, cfg.autoScreenshotSeconds * 20);
				if (cfg.autoScreenshot && ticks % shotEvery == 0 && client.level != null) {
					Shot.capture(client, "auto");
				}
				while (openKey.consumeClick()) {
					client.setScreenAndShow(new VaultScreen(client.gui.screen()));
				}
			} catch (Exception ignored) {
			}
		});
		ScreenEvents.AFTER_INIT.register((client, screen, width, height) -> {
			if (!VaultConfig.get().titleButton) return;
			if (screen instanceof TitleScreen) {
				if (VaultConfig.get().openOnLaunch && !openedLaunch) {
					openedLaunch = true;
					client.execute(() -> client.setScreenAndShow(new VaultScreen(screen)));
					return;
				}
				placeButton(screen, width, height, client);
			} else if (screen instanceof PauseScreen) {
				placeButton(screen, width, height, client);
			}
		});
		Thread.UncaughtExceptionHandler previous = Thread.getDefaultUncaughtExceptionHandler();
		Thread.setDefaultUncaughtExceptionHandler((thread, error) -> {
			StenNet.reportCrash("uncaught:" + thread.getName(), error);
			if (previous != null) previous.uncaughtException(thread, error);
		});
	}

	private static void placeButton(net.minecraft.client.gui.screens.Screen screen, int width, int height, net.minecraft.client.Minecraft client) {
		int x = width / 2 + 104;
		int y = height / 4 + 48;
		int w = 110;
		int h = 20;
		for (var widget : Screens.getWidgets(screen)) {
			if (widget instanceof AbstractWidget button && button.getWidth() >= 150 && button.getHeight() >= 18) {
				x = button.getX() + button.getWidth() + 4;
				y = button.getY();
				h = button.getHeight();
				if (x + w > width - 8) {
					x = Math.max(8, button.getX() - w - 4);
				}
				break;
			}
		}
		Screens.getWidgets(screen).add(new GlassButton(
			x,
			y,
			w,
			h,
			Component.literal("STEN Vault"),
			true,
			button -> client.setScreenAndShow(new VaultScreen(screen))
		));
	}
}
