package eu.jonahbauer.wizard.client.libgdx.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.listeners.ResetErrorListener;
import eu.jonahbauer.wizard.client.libgdx.state.AwaitingJoinSession;
import eu.jonahbauer.wizard.client.libgdx.state.Lobby;
import eu.jonahbauer.wizard.common.messages.client.CreateSessionMessage;
import eu.jonahbauer.wizard.common.model.Configuration;

public class CreateGameScreen extends MenuScreen {
    
    private TextButton buttonBack;
    private TextButton buttonContinue;

    private TextField sessionName;
    private TextField playerName;
    private TextField timeOut;
    private SelectBox<String> configurations;

    private final Lobby state;

    private final ChangeListener listener = new ChangeListener() {
        @Override
        public void changed(ChangeEvent event, Actor actor) {
            if (actor == buttonBack) {
                game.setScreen(new LobbyScreen(game));
                sfxClick();
            } else if (actor == buttonContinue) {
                create();
                sfxClick();
            }
        }
    };
    
    public CreateGameScreen(WizardGame game) {
        super(game);
        this.state = (Lobby) game.getClient().getState();
    }
    
    @Override
    public void show() {
        super.show();

        buttonBack = new TextButton(game.messages.get("menu.create_game.back"), game.data.skin);
        buttonBack.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
        buttonContinue = new TextButton(game.messages.get("menu.create_game.create"), game.data.skin);
        buttonContinue.setPosition(WizardGame.WIDTH * 0.725f - buttonContinue.getWidth(), BUTTON_BAR_Y);

        var errorListener = new ResetErrorListener(game.data.skin);

        sessionName = new TextField("", game.data.skin);
        sessionName.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.5f);
        sessionName.setSize(0.4f * WizardGame.WIDTH, 64);
        sessionName.addListener(errorListener);
        sessionName.setProgrammaticChangeEvents(true);

        playerName = new TextField(state.getPlayerName(), game.data.skin);
        playerName.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.45f);
        playerName.setSize(0.4f * WizardGame.WIDTH, 64);
        playerName.addListener(errorListener);
        var playerNameListener = new ChangeListener() {
            private final String format = game.messages.get("menu.create_game.session_name.default");

            @Override
            public void changed(ChangeEvent event, Actor actor) {
                var old = state.getPlayerName();
                state.setPlayerName(playerName.getText());

                var player = playerName.getText();
                var session = sessionName.getText();
                if (session.isEmpty() || session.equals(format.formatted(old))) {
                    if (player.isEmpty()) {
                        sessionName.setText("");
                    } else {
                        sessionName.setText(format.formatted(player));
                    }
                }
            }
        };
        playerName.addListener(playerNameListener);
        playerNameListener.changed(null, null);

        timeOut = new TextField("", game.data.skin);
        timeOut.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.4f);
        timeOut.setSize(0.4f * WizardGame.WIDTH, 64);
        timeOut.setTextFieldFilter(new TextField.TextFieldFilter.DigitsOnlyFilter());
        timeOut.addListener(errorListener);
        
        configurations = new SelectBox<>(game.data.skin);
        configurations.setSize(400, 64);
        configurations.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.3f);
        configurations.addListener(errorListener);
        
        Array<String> values = new Array<>();
        for (Configuration value : Configuration.values()) {
            values.add(value.toString());
        }
        configurations.setItems(values);
    
        var contentTable = new Table().center().left();
        contentTable.columnDefaults(0).growX().width(0.4f * WizardGame.WIDTH - 20);
        contentTable.setSize(0.4f * WizardGame.WIDTH - 20, 400);
        contentTable.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.3f);
        
        contentTable.add(new Label(game.messages.get("menu.create_game.player_name.label"), game.data.skin)).row();
        contentTable.add(playerName).row();
        contentTable.add(new Label(game.messages.get("menu.create_game.session_name.label"), game.data.skin)).row();
        contentTable.add(sessionName).row();
        contentTable.add(new Label(game.messages.get("menu.create_game.session_timeout.label"), game.data.skin)).row();
        contentTable.add(timeOut).row();
        contentTable.add(new Label(game.messages.get("menu.create_game.session_configuration.label"), game.data.skin)).row();
        contentTable.add(configurations).row();

        Gdx.input.setInputProcessor(game.data.stage);
        game.data.stage.addActor(buttonContinue);
        game.data.stage.addActor(contentTable);
        game.data.stage.addActor(buttonBack);
        
        buttonContinue.addListener(listener);
        buttonBack.addListener(listener);
    }

    private void create() {
        boolean error = false;

        String sessionName = this.sessionName.getText();
        if (sessionName.isBlank()) {
            System.out.println("Please choose a session name.");
            this.sessionName.setStyle(game.data.skin.get("error", TextField.TextFieldStyle.class));
            error = true;
        }

        String playerName = this.playerName.getText();
        if (playerName.isBlank()) {
            System.out.println("Please choose a name.");
            this.playerName.setStyle(game.data.skin.get("error", TextField.TextFieldStyle.class));
            error = true;
        }

        long timeout = 0;
        try {
            timeout = Long.parseLong(this.timeOut.getText());
        } catch (NumberFormatException e) {
            System.out.println("Please choose a valid timeout.");
            this.timeOut.setStyle(game.data.skin.get("error", TextField.TextFieldStyle.class));
            error = true;
        }

        Configuration config = null;
        try {
            int selected = configurations.getSelectedIndex();
            config = Configuration.values()[selected];
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Please select a valid configuration.");
            this.configurations.setStyle(game.data.skin.get("error", SelectBox.SelectBoxStyle.class));
            error = true;
        }

        if (!error) {
            var client = game.getClient();
            client.transition(new AwaitingJoinSession(null, sessionName, config, playerName));
            client.send(new CreateSessionMessage(sessionName, playerName, 1000 * timeout, config));
        }
    }
}
