package cz.jzitnik;

import com.googlecode.lanterna.input.KeyStroke;
import com.googlecode.lanterna.screen.TerminalScreen;
import com.googlecode.lanterna.terminal.DefaultTerminalFactory;
import com.googlecode.lanterna.terminal.MouseCaptureMode;
import cz.jzitnik.annotations.Dependency;
import cz.jzitnik.annotations.injectors.InjectDependency;
import cz.jzitnik.annotations.injectors.InjectState;
import cz.jzitnik.events.KeyboardPressEvent;
import cz.jzitnik.events.MouseAction;
import cz.jzitnik.events.TerminalResizeEvent;
import cz.jzitnik.states.RunningState;
import cz.jzitnik.states.TerminalState;
import cz.jzitnik.utils.events.EventManager;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

@Slf4j
@Dependency
public class Cli implements Runnable {
    @InjectDependency
    private EventManager eventManager;

    @InjectState
    private TerminalState terminalState;

    @InjectState
    private RunningState runningState;

    @Override
    public void run() {
        eventManager.start(); // Start event manager thread

        try (TerminalScreen terminal = new DefaultTerminalFactory()
                .setMouseCaptureMode(MouseCaptureMode.CLICK_RELEASE_DRAG_MOVE)
                .createScreen()) {
            terminalState.setTerminalScreen(terminal);
            terminalState.setTextGraphics(terminal.newTextGraphics());

            terminal.setCursorPosition(null);
            terminal.doResizeIfNecessary();

            terminal.getTerminal().addResizeListener((_, terminalSize) -> {
                terminal.doResizeIfNecessary();
                eventManager.emitEvent(new TerminalResizeEvent(terminalSize));
            });

            terminal.startScreen();

            eventManager.emitEvent(new TerminalResizeEvent(terminal.getTerminalSize()));

            while (runningState.isRunning()) {
                KeyStroke keyStroke = terminal.readInput();
                if (keyStroke != null) {
                    if (keyStroke instanceof com.googlecode.lanterna.input.MouseAction mouse) {
                        eventManager.emitEvent(new MouseAction(mouse));
                        continue;
                    }

                    eventManager.emitEvent(new KeyboardPressEvent(keyStroke));
                }
            }
        } catch (IOException e) {
            log.error("Terminal error occurred, shutting down CLI thread.", e);
            throw new RuntimeException(e);
        }
    }
}
