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

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.*;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.listeners.KeyboardFocusManager;
import eu.jonahbauer.wizard.client.libgdx.listeners.ResetErrorListener;
import eu.jonahbauer.wizard.client.libgdx.state.Lobby;
import lombok.extern.log4j.Log4j2;

import java.util.UUID;

@Log4j2
public class RejoinScreen extends MenuScreen {

    private TextButton buttonBack;
    private TextButton buttonContinue;

    private TextField sessionUUID;
    private TextField playerUUID;
    private TextField secret;

    private final ChangeListener listener = new ChangeListener() {
        @Override
        public void changed(ChangeEvent event, Actor actor) {
            if (actor == buttonBack) {
                game.getClient().execute(Lobby.class, Lobby::showListScreen);
            } else if (actor == buttonContinue) {
                rejoin();
            }
        }
    };

    public RejoinScreen(WizardGame game) {
        super(game);
    }

    @Override
    public void show() {
        super.show();

        var credentials = game.storage.credentials;

        buttonBack = new TextButton(messages.get("menu.rejoin.back"), skin);
        buttonBack.addListener(listener);
        getButtonGroup().addActor(buttonBack);

        buttonContinue = new TextButton(messages.get("menu.rejoin.continue"), skin);
        buttonContinue.addListener(listener);
        getButtonGroup().addActor(buttonContinue);

        var errorListener = new ResetErrorListener(skin);

        sessionUUID = new TextField(credentials != null ? credentials.session().toString() : null , skin);
        sessionUUID.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.5f);
        sessionUUID.setSize(0.4f * WizardGame.WIDTH, 64);
        sessionUUID.addListener(errorListener);
        sessionUUID.setProgrammaticChangeEvents(true);

        playerUUID = new TextField(credentials != null ? credentials.player().toString() : null, skin);
        playerUUID.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.45f);
        playerUUID.setSize(0.4f * WizardGame.WIDTH, 64);
        playerUUID.addListener(errorListener);

        secret = new TextField(credentials != null ? credentials.secret() : null, skin);
        secret.setPosition(WizardGame.WIDTH * 0.3f, WizardGame.HEIGHT * 0.4f);
        secret.setSize(0.4f * WizardGame.WIDTH, 64);
        secret.addListener(errorListener);

        var contentTable = new Table(skin).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(messages.get("menu.rejoin.session_uuid.label")).row();
        contentTable.add(sessionUUID).row();
        contentTable.add(messages.get("menu.rejoin.player_uuid.label")).row();
        contentTable.add(playerUUID).row();
        contentTable.add(messages.get("menu.rejoin.player_secret.label")).row();
        contentTable.add(secret).row();

        stage.addActor(contentTable);
        stage.addCaptureListener(new KeyboardFocusManager(sessionUUID, playerUUID, secret, buttonBack, buttonContinue));

        buttonBack.setName("button_back");
        buttonContinue.setName("button_continue");
        sessionUUID.setName("session_uuid");
        playerUUID.setName("player_uuid");
        secret.setName("player_secret");
    }

    private void rejoin() {
        boolean error = false;

        String sessionUUIDText = this.sessionUUID.getText();
        UUID sessionUUID = null;
        if (sessionUUIDText.isBlank()) {
            log.warn("Please enter the session uuid.");
            this.sessionUUID.setStyle(getTextFieldErrorStyle());
            error = true;
        } else {
            try {
                sessionUUID = UUID.fromString(sessionUUIDText);
            } catch (IllegalArgumentException e) {
                log.warn("Please enter a valid session uuid.");
                this.sessionUUID.setStyle(getTextFieldErrorStyle());
                error = true;
            }
        }

        String playerUUIDText = this.playerUUID.getText();
        UUID playerUUID = null;
        if (playerUUIDText.isBlank()) {
            log.warn("Please enter the player uuid.");
            this.playerUUID.setStyle(getTextFieldErrorStyle());
            error = true;
        } else {
            try {
                playerUUID = UUID.fromString(playerUUIDText);
            } catch (IllegalArgumentException e) {
                log.warn("Please enter a valid player uuid.");
                this.playerUUID.setStyle(getTextFieldErrorStyle());
                error = true;
            }
        }

        String playerSecret = this.secret.getText();
        if (playerSecret.isBlank()) {
            log.warn("Please enter the player secret.");
            this.secret.setStyle(getTextFieldErrorStyle());
            error = true;
        }

        var fPlayerUUID = playerUUID;
        var fSessionUUID = sessionUUID;
        if (!error) {
            var client = game.getClient();
            try {
                client.execute(Lobby.class, (s, c) -> s.rejoinSession(c, fSessionUUID, fPlayerUUID, playerSecret));
            } catch (IllegalArgumentException e) {
                // only if session is not known
                log.warn(e.getMessage());
                this.sessionUUID.setStyle(getTextFieldErrorStyle());
            }
        }
    }
}
