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 eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.AutoFocusScrollPane;
import eu.jonahbauer.wizard.client.libgdx.state.AwaitingJoinLobby;
import eu.jonahbauer.wizard.client.libgdx.state.Session;
import eu.jonahbauer.wizard.common.messages.client.LeaveSessionMessage;
import eu.jonahbauer.wizard.common.messages.client.ReadyMessage;
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
import eu.jonahbauer.wizard.common.model.Configuration;

import java.util.UUID;

public class WaitingScreen extends MenuScreen {
    
    private TextButton buttonLeave;
    private TextButton buttonReady;
    
    private Label labelSessionName;
    private Label labelSessionUUID;
    private Label labelSessionConfiguration;
    private Label labelPlayerName;
    
    private List<PlayerData> players;
    
    private AutoFocusScrollPane listContainer;
    
    private final ChangeListener listener = new ChangeListener() {
        @Override
        public void changed(ChangeEvent event, Actor actor) {
            if (actor == buttonLeave) {
                game.getClient().transition(new AwaitingJoinLobby());
                game.getClient().send(new LeaveSessionMessage());
                sfxClick();
            } else if (actor == buttonReady) {
                var state = (Session) game.getClient().getState();
                state.setNextReady(!state.isReady());
                game.getClient().send(new ReadyMessage(!state.isReady()));
                buttonReady.setDisabled(true);
                sfxClick();
            }
        }
    };

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

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

        buttonLeave = new TextButton(game.messages.get("menu.waiting.leave"), game.data.skin);
        buttonLeave.setPosition(WizardGame.WIDTH * 0.275f, BUTTON_BAR_Y);
        buttonReady = new TextButton(game.messages.get("menu.waiting.ready"), game.data.skin);
        buttonReady.setPosition(WizardGame.WIDTH * 0.725f - buttonReady.getWidth(), BUTTON_BAR_Y);

        players = new List<>(game.data.skin) {
            @Override
            public String toString(PlayerData player) {
                return player.getName();
            }
        };

        listContainer = new AutoFocusScrollPane(players, game.data.skin);
        listContainer.layout();

        var content = new HorizontalGroup().grow().space(20);
        content.setPosition(0.25f * WizardGame.WIDTH, 0.3f * WizardGame.HEIGHT);
        content.setSize(0.5f * WizardGame.WIDTH, 400);
        content.addActor(new Container<>(listContainer).width(0.2f * WizardGame.WIDTH).height(400));
        content.addActor(createInfoTable());
        content.layout();

        Gdx.input.setInputProcessor(game.data.stage);
        game.data.stage.addActor(buttonLeave);
        game.data.stage.addActor(buttonReady);
        game.data.stage.addActor(content);

        buttonLeave.addListener(listener);
        buttonReady.addListener(listener);
    }

    public void setReady(boolean ready) {
        buttonReady.setDisabled(false);
        buttonReady.setText(game.messages.get(ready ? "menu.waiting.not_ready" : "menu.waiting.ready"));
    }
    
    public void addPlayer(PlayerData player) {
        this.players.getItems().add(player);
        var items = this.players.getItems();
        for (int i = 0; i < items.size; i++) {
            if (items.get(i).getUuid().equals(player.getUuid())) {
                items.set(i, player);
                break;
            }
        }
        this.players.invalidateHierarchy();
    }
    
    public void removePlayer(UUID player) {
        var items = this.players.getItems();
        for (int i = 0; i < items.size; i++) {
            if (items.get(i).getUuid().equals(player)) {
                items.removeIndex(i);
                break;
            }
        }
        this.players.invalidateHierarchy();
    }
    
    public void modifyPlayer(PlayerData data) {
        var items = this.players.getItems();
        for (int i = 0; i < items.size; i++) {
            if (items.get(i).getUuid().equals(data.getUuid())) {
                items.set(i, data);
                break;
            }
        }
        this.players.invalidateHierarchy();
    }
    
    public void setPlayers(PlayerData... players) {
        var items = this.players.getItems();
        items.clear();
        items.addAll(players);
        this.players.invalidateHierarchy();
    }
    
    public void setSession(UUID uuid, String name, Configuration configuration) {
        this.labelSessionName.setText(name);
        this.labelSessionUUID.setText(uuid.toString());
        this.labelSessionConfiguration.setText(configuration.toString());
    }
    
    public void setPlayerName(String name) {
        this.labelPlayerName.setText(name);
    }
    
    private Table createInfoTable() {
        float infoTableWidth = 0.3f * WizardGame.WIDTH - 20;
    
        labelSessionName = new Label("", game.data.skin, "textfield");
        labelSessionUUID = new Label("", game.data.skin, "textfield");
        labelSessionConfiguration = new Label("", game.data.skin, "textfield");
        labelPlayerName = new Label("", game.data.skin, "textfield");
    
        labelSessionName.setEllipsis(true);
        labelSessionUUID.setEllipsis(true);
        labelSessionConfiguration.setEllipsis(true);
        labelPlayerName.setEllipsis(true);
        
        var infoTable = new Table().center().left();
        infoTable.columnDefaults(0).growX().width(infoTableWidth);
        infoTable.setSize(infoTableWidth, 400);
        
        infoTable.add(new Label(game.messages.get("menu.waiting.session_name.label"), game.data.skin)).row();
        infoTable.add(labelSessionName).row();
        infoTable.add(new Label(game.messages.get("menu.waiting.session_uuid.label"), game.data.skin)).row();
        infoTable.add(labelSessionUUID).row();
        infoTable.add(new Label(game.messages.get("menu.waiting.session_configuration.label"), game.data.skin)).row();
        infoTable.add(labelSessionConfiguration).row();
        infoTable.add(new Label(game.messages.get("menu.waiting.player_name.label"), game.data.skin)).row();
        infoTable.add(labelPlayerName).row();
        
        return infoTable;
    }
}
