package pp.monopoly.client;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.texture.Texture;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.style.BaseStyles;

import pp.dialog.DialogBuilder;
import pp.dialog.DialogManager;
import pp.graphics.Draw;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.game.client.ClientGameLogic;
import pp.monopoly.game.client.MonopolyClient;
import pp.monopoly.game.client.ServerConnection;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.InfoTextEvent;

public class MonopolyApp extends SimpleApplication implements MonopolyClient, GameEventListener {
    private BitmapText topText;
    private final ServerConnection serverConnection;
    private final ClientGameLogic logic;
    private final MonopolyAppConfig config;
    private final ActionListener escapeListener = (name, isPressed, tpf) -> handleEscape(isPressed);
    private final DialogManager dialogManager = new DialogManager(this);
    private final ExecutorService executor = Executors.newCachedThreadPool();
    private SettingsMenu settingsMenu;
    private final Draw draw;

    private boolean isSettingsMenuOpen = false;

    public static void main(String[] args) {
        new MonopolyApp().start();
    }

    public MonopolyApp() {
        this.draw = new Draw(assetManager);
        config = new MonopolyAppConfig();
        serverConnection = new NetworkSupport(this);
        logic = new ClientGameLogic(serverConnection);
        logic.addListener(this);
        setShowSettings(config.getShowSettings());
        setSettings(makeSettings());
    }

    /**
     * Creates and configures application settings from the client configuration.
     *
     * @return A configured {@link AppSettings} object.
     */
    private AppSettings makeSettings() {
        final AppSettings settings = new AppSettings(true);
        settings.setTitle(lookup("monopoly.name"));
        settings.setResolution(config.getResolutionWidth(), config.getResolutionHeight());
        settings.setFullscreen(config.fullScreen());
        settings.setUseRetinaFrameBuffer(config.useRetinaFrameBuffer());
        settings.setGammaCorrection(config.useGammaCorrection());
        return settings;
    }

    /**
     * Factory method for creating a server connection based on the current
     * client configuration.
     *
     * @return A {@link ServerConnection} instance, which could be a real or mock server.
     */
    private ServerConnection makeServerConnection() {
        return new NetworkSupport(this);
    }

    /**
     * Returns the dialog manager responsible for managing in-game dialogs.
     *
     * @return The {@link DialogManager} instance.
     */
    public DialogManager getDialogManager() {
        return dialogManager;
    }

    /**
     * Returns the game logic handler for the client.
     *
     * @return The {@link ClientGameLogic} instance.
     */
    @Override
    public ClientGameLogic getGameLogic() {
        return logic;
    }

    /**
     * Returns the current configuration settings for the Monopoly client.
     *
     * @return The {@link MonopolyClientConfig} instance.
     */
    @Override
    public MonopolyAppConfig getConfig() {
        return config;
    }

    @Override
    public ClientGameLogic getGameLogic() {
        return logic;
    }

    private AppSettings makeSettings() {
        final AppSettings settings = new AppSettings(true);
        settings.setTitle("Monopoly Game");
        settings.setResolution(config.getResolutionWidth(), config.getResolutionHeight());
        settings.setFullscreen(config.fullScreen());
        return settings;
    }

    public boolean isSettingsMenuOpen() {
        return isSettingsMenuOpen;
    }

    public void setSettingsMenuOpen(boolean isOpen) {
        this.isSettingsMenuOpen = isOpen;
    }

    @Override
    public void simpleInitApp() {
        GuiGlobals.initialize(this); 
        BaseStyles.loadGlassStyle();
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");

        setupInput();
        setupGui();

        // Initialisiere das Startmenü
        StartMenu.createStartMenu(this);
    }

    private void setupGui() {
        BitmapFont normalFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
        topText = new BitmapText(normalFont);
        topText.setLocalTranslation(10, settings.getHeight() - 10, 0);
        guiNode.attachChild(topText);
    }

    private void setupInput() {
        inputManager.deleteMapping(INPUT_MAPPING_EXIT);
        inputManager.setCursorVisible(true);
        inputManager.addMapping("ESC", new KeyTrigger(KeyInput.KEY_ESCAPE));
        inputManager.addListener(escapeListener, "ESC");
    }
    

    private void handleEscape(boolean isPressed) {
        if (isPressed) {
            if (isSettingsMenuOpen && settingsMenu != null) {
                settingsMenu.close();
                setSettingsMenuOpen(false);
            } else {
                settingsMenu = new SettingsMenu(this);
                settingsMenu.open();
                setSettingsMenuOpen(true);
            }
        }
    }


    void setInfoText(String text) {
        topText.setText(text);
    }

    @Override
    public void receivedEvent(InfoTextEvent event) {
        setInfoText(event.key());
    }

    @Override
    public void stop(boolean waitFor) {
        if (executor != null) executor.shutdownNow();
        serverConnection.disconnect();
        super.stop(waitFor);
    }

    public DialogManager getDialogManager() {
        return dialogManager;
    }

    public Draw getDraw() {
        return draw;
    }

    public ExecutorService getExecutor() {
        return executor;
    }

    public void closeApp() {
        stop();
    }

    public void errorDialog(String errorMessage) {
        DialogBuilder.simple(dialogManager)
                .setTitle("Fehler")
                .setText(errorMessage)
                .setOkButton("OK")
                .build()
                .open();
    }
    //altes Fenster beim Start von TestWorld schließen
    public void startTestWorld() {
     // Entferne die aktuelle GUI
     guiNode.detachAllChildren();
    
     // Erstelle ein Quadrat mit Textur
     Box box = new Box(1, 0.01f, 1);  // Dünnes Quadrat
     Geometry geom = new Geometry("Box", box);
    
     // Setze das Material mit Textur
     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     Texture texture = assetManager.loadTexture("Pictures/board.png");
     mat.setTexture("ColorMap", texture);
     geom.setMaterial(mat);
    
     // Füge das Quadrat zur Szene hinzu
     rootNode.attachChild(geom);
    
     // Setze die Kameraposition
     cam.setLocation(new Vector3f(0, 0, 3));
     cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y);
    }
    public void returnToMenu() {
        // Entferne die Testszene
        rootNode.detachAllChildren();
    
        // Zeige das Startmenü erneut
        StartMenu.createStartMenu(this);
    }
    

}
