package cz.jzitnik;

import cz.jzitnik.game.GameSaver;
import cz.jzitnik.game.logic.CustomLogicProvider;
import cz.jzitnik.game.mobs.EntityLogicProvider;
import cz.jzitnik.game.threads.ThreadProvider;
import cz.jzitnik.game.ui.*;
import cz.jzitnik.game.SpriteLoader;
import cz.jzitnik.tui.ScreenRenderer;
import lombok.extern.slf4j.Slf4j;

import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;

import java.io.IOException;

/**
 * The main class that starts the whole game. It initializes providers and sets
 * up a terminal and creates the main game loop.
 */
@Slf4j
public class Main {
    public static void main(String[] args) {
        try {
            log.info("Setting up terminal");
            Terminal terminal = TerminalBuilder.terminal();
            terminal.enterRawMode();

            if (!terminal.hasMouseSupport()) {
                log.error("This terminal does not support mouse");
                System.exit(1);
            }

            terminal.trackMouse(Terminal.MouseTracking.Any);

            var spriteList = SpriteLoader.load();
            var screenRenderer = new ScreenRenderer(spriteList, terminal);
            var gameSaver = new GameSaver();
            var game = gameSaver.load();

            final boolean[] isRunning = { true };

            EntityLogicProvider entityLogicProvider = new EntityLogicProvider();
            CustomLogicProvider customLogicProvider = new CustomLogicProvider();

            ThreadProvider threadProvider = new ThreadProvider(game, screenRenderer, terminal, isRunning);
            threadProvider.start();

            while (isRunning[0]) {
                try {
                    entityLogicProvider.update(game);
                } catch (Exception ignored) {
                    // Yeah, yeah I know. Deal with it
                }
                try {
                    customLogicProvider.update(game, screenRenderer);
                } catch (Exception e) {
                    e.printStackTrace();
                }

                if (game.getWindow() == Window.WORLD) {
                    screenRenderer.render(game);
                }

                Thread.sleep(1000);
            }

            log.info("Closing terminal");
            terminal.trackMouse(Terminal.MouseTracking.Off);
            terminal.close();
        } catch (IOException | InterruptedException ignored) {
        }
    }
}
