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 com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import eu.jonahbauer.wizard.client.libgdx.UiskinAtlas;
import eu.jonahbauer.wizard.client.libgdx.WizardGame;
import eu.jonahbauer.wizard.client.libgdx.actors.IconList;
import eu.jonahbauer.wizard.client.libgdx.listeners.KeyboardFocusManager;
import eu.jonahbauer.wizard.client.libgdx.state.Session;
import eu.jonahbauer.wizard.common.messages.data.PlayerData;
import eu.jonahbauer.wizard.common.model.Configuration;

import java.util.UUID;

public class SessionScreen 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 final ChangeListener listener = new ChangeListener() {
        @Override
        public void changed(ChangeEvent event, Actor actor) {
            if (actor == buttonLeave) {
                game.getClient().execute(Session.class, Session::leave);
            } else if (actor == buttonReady) {
                game.getClient().execute(Session.class, Session::toggleReady);
            }
        }
    };

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

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

        buttonLeave = new TextButton(messages.get("menu.session.leave"), skin);
        buttonLeave.addListener(listener);
        getButtonGroup().addActor(buttonLeave);

        buttonReady = new TextButton(messages.get("menu.session.ready"), skin);
        buttonReady.addListener(listener);
        getButtonGroup().addActor(buttonReady);

        getButtonGroup().setWidth(0.55f * WizardGame.WIDTH);

        players = new IconList<>(skin) {
            private final Drawable ready = skin.getDrawable(UiskinAtlas.READY);
            private final Drawable notReady = skin.getDrawable(UiskinAtlas.NOT_READY);

            @Override
            public String toString(PlayerData player) {
                return player.getName();
            }

            @Override
            public Drawable getIcon(PlayerData item) {
                return item.isReady() ? ready : notReady;
            }
        };

        var listContainer = new ScrollPane(players, 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();

        stage.addActor(content);
        stage.addCaptureListener(new KeyboardFocusManager(buttonLeave, buttonReady));

        buttonLeave.setName("button_leave");
        buttonReady.setName("button_ready");
        labelSessionName.setName("session_name");
        labelSessionUUID.setName("session_uuid");
        labelSessionConfiguration.setName("session_configuration");
        labelPlayerName.setName("player_name");
    }

    private Table createInfoTable() {
        float infoTableWidth = 0.3f * WizardGame.WIDTH - 20;

        labelSessionName = new Label("", skin, "textfield");
        labelSessionUUID = new Label("", skin, "textfield");
        labelSessionConfiguration = new Label("", skin, "textfield");
        labelPlayerName = new Label("", skin, "textfield");

        labelSessionName.setEllipsis(true);
        labelSessionUUID.setEllipsis(true);
        labelSessionConfiguration.setEllipsis(true);
        labelPlayerName.setEllipsis(true);

        var infoTable = new Table(skin).center().left();
        infoTable.columnDefaults(0).growX().width(infoTableWidth);
        infoTable.setSize(infoTableWidth, 400);

        infoTable.add(messages.get("menu.session.session_name.label")).row();
        infoTable.add(labelSessionName).row();
        infoTable.add(messages.get("menu.session.session_uuid.label")).row();
        infoTable.add(labelSessionUUID).row();
        infoTable.add(messages.get("menu.session.session_configuration.label")).row();
        infoTable.add(labelSessionConfiguration).row();
        infoTable.add(messages.get("menu.session.player_name.label")).row();
        infoTable.add(labelPlayerName).row();

        return infoTable;
    }

    public void setSending(boolean sending) {
        buttonReady.setDisabled(sending);
    }

    public void setReady(boolean ready) {
        buttonReady.setText(messages.get(ready ? "menu.session.not_ready" : "menu.session.ready"));
    }
    
    public void addPlayer(PlayerData player) {
        this.players.getItems().add(player);
        this.players.invalidateHierarchy();
    }
    
    public void removePlayer(UUID player) {
        var index = indexOf(player);
        if (index != -1) {
            this.players.getItems().removeIndex(index);
            this.players.invalidateHierarchy();
        }
    }
    
    public void modifyPlayer(PlayerData data) {
        var index = indexOf(data.getUuid());
        this.players.getItems().set(index, data);
        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 int indexOf(UUID player) {
        var items = this.players.getItems();
        for (int i = 0; i < items.size; i++) {
            if (items.get(i).getUuid().equals(player)) {
                return i;
            }
        }
        return -1;
    }
}
