package cz.jzitnik.game.ui;

import org.jline.terminal.MouseEvent;
import org.jline.terminal.Terminal;
import cz.jzitnik.game.Game;
import cz.jzitnik.game.sprites.ui.Font.*;
import cz.jzitnik.tui.ScreenRenderer;
import cz.jzitnik.tui.utils.Menu;

/**
 * Handles the in-game escape menu functionality, including rendering options,
 * handling mouse input, and managing save and exit logic.
 */
public class Escape {
    private Game game;
    private Menu menu;

    /**
     * Constructs the Escape menu for the given game instance.
     *
     * @param game The current game instance.
     */
    public Escape(Game game) {
        this.game = game;
        this.menu = new Menu(game, "2DCraft", new String[] { "Continue", "Options", "Save and exit" },
                this::onButtonClick);
    }

    /**
     * Resets the escape menu to its initial state.
     */
    public void reset() {
        menu.reset();
    }

    /**
     * Renders the escape menu onto the screen.
     *
     * @param buffer   The buffer to which rendering output is appended.
     * @param terminal The terminal used to get display properties.
     */
    public void render(StringBuilder buffer, Terminal terminal) {
        menu.render(buffer, terminal);
    }

    /**
     * Handles mouse input events within the escape menu.
     *
     * @param mouseEvent     The mouse event triggered by the user.
     * @param terminal       The terminal used for input/output.
     * @param screenRenderer The screen renderer for drawing changes.
     */
    public void mouse(MouseEvent mouseEvent, Terminal terminal, ScreenRenderer screenRenderer) {
        menu.handleMouse(mouseEvent, terminal, screenRenderer);
    }

    /**
     * Renders a "Saving" screen with centered large-font text.
     *
     * @param buffer   The buffer to which rendering output is appended.
     * @param terminal The terminal used to calculate screen size.
     */
    private void onButtonClick(int index, ScreenRenderer screenRenderer) {
        switch (index) {
            case 0:
                game.setWindow(Window.WORLD);
                break;
            case 1:
                game.setWindow(Window.OPTIONS);
                break;
            case 2:
                game.setWindow(Window.SAVE_EXIT);
                screenRenderer.render(game);
                game.getGameStates().dependencies.gameSaver.save(game);
                game.setWindow(Window.SAVED);
                screenRenderer.render(game);
                System.exit(0);
                break;
        }
        screenRenderer.render(game);
    }

    /**
     * Renders a "Saved" screen with centered large-font text.
     *
     * @param buffer   The buffer to which rendering output is appended.
     * @param terminal The terminal used to calculate screen size.
     */
    public void renderSave(StringBuilder buffer, Terminal terminal) {
        var font = game.getGameStates().dependencies.font;
        var savingText = font.line(terminal, "Saving", Size.LARGE, Align.CENTER);

        int top = (terminal.getHeight() - savingText.getHeight()) / 2;

        buffer.append("\n".repeat(top));
        buffer.append(savingText.getData());
    }

    /**
     * Callback for when a button in the escape menu is clicked.
     *
     * @param index           The index of the clicked button (0 = Continue, 1 = Options, 2 = Save and exit).
     * @param screenRenderer  The screen renderer used to refresh the display.
     */
    public void renderSaved(StringBuilder buffer, Terminal terminal) {
        var font = game.getGameStates().dependencies.font;
        var savingText = font.line(terminal, "Saved", Size.LARGE, Align.CENTER);

        int top = (terminal.getHeight() - savingText.getHeight()) / 2;

        buffer.append("\n".repeat(top));
        buffer.append(savingText.getData());
    }
}
