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

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.ScaleToAction;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.utils.Align;
import eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings;
import lombok.Setter;
import org.jetbrains.annotations.Range;

public class PadOfTruth extends Table {
    public static final float EXTENDED_WIDTH = 636;
    public static final float EXTENDED_HEIGHT = 824;
    public static final float COLLAPSED_SCALE = CardActor.PREF_HEIGHT / EXTENDED_HEIGHT;

    private final Label[] names = new Label[6];
    private final Label[][] predictions = new Label[20][];
    private final Label[][] scores = new Label[20][];

    @Setter
    private boolean enabled = true;

    public PadOfTruth(Skin skin, Drawable background) {
        super(skin);
        setTouchable(Touchable.enabled);
        setBackground(background);

        setWidth(EXTENDED_WIDTH);
        setHeight(EXTENDED_HEIGHT);

        setTransform(true);
        setScale(COLLAPSED_SCALE);

        addListener(new InputListener() {
            private ScaleToAction action;

            @Override
            public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
                if (!enabled) return;
                if (fromActor != null && isAscendantOf(fromActor)) return;
                if (action != null) removeAction(action);
                action = Actions.scaleTo(1, 1, AnimationTimings.PAD_OF_TRUTH_EXPAND);
                addAction(action);
            }

            @Override
            public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) {
                if (!enabled) return;
                if (toActor != null && isAscendantOf(toActor)) return;
                if (action != null) removeAction(action);
                action = Actions.scaleTo(COLLAPSED_SCALE, COLLAPSED_SCALE, AnimationTimings.PAD_OF_TRUTH_COLLAPSE);
                addAction(action);
            }
        });

        setRound(false);
        pad(20, 45, 25, 25);
        align(Align.topLeft);
        clip();

        for (int i = 0; i < 6; i++) {
            columnDefaults(2 * i).width(57f).center().pad(2, 4, 2, 4);
            columnDefaults(2 * i + 1).width(22f).center().pad(2, 4, 2, 4);
        }

        for (int player = 0; player < 6; player++) {
            var cell = add("", "handwritten").height(46f).width(87f).colspan(2);
            names[player] = cell.getActor();
            names[player].setEllipsis(true);
        }
        row();

        for (int round = 0; round < 20; round++) {
            int players = MathUtils.clamp(60 / (round + 1), 3, 6);
            predictions[round] = new Label[players];
            scores[round] = new Label[players];
            for (int player = 0; player < players; player++) {
                scores[round][player] = add("", "handwritten").height(32.5f).center().getActor();
                predictions[round][player] = add("", "handwritten").height(32.5f).center().getActor();

                scores[round][player].setAlignment(Align.center);
                predictions[round][player].setAlignment(Align.center);
            }
            row();
        }
    }

    public void setName(int player, String name) {
        names[player].setText(name);
    }

    public void setScore(int player, @Range(from = 0, to = 19) int round, int score) {
        scores[round][player].setText(String.valueOf(score));
    }

    public void setPrediction(int player, @Range(from = 0, to = 19) int round, int prediction) {
        predictions[round][player].setText(String.valueOf(prediction));
    }

    public void checkPosition(int player, int round) {
        if (round < 0 || round >= predictions.length || round >= scores.length) throw new ArrayIndexOutOfBoundsException(round);
        if (player < 0 || player >= predictions[round].length || player >= scores[round].length) throw new ArrayIndexOutOfBoundsException(player);
    }

    public void clearValues() {
        for (var row : predictions) {
            for (var label : row) {
                label.setText(null);
            }
        }

        for (var row : scores) {
            for (var label : row) {
                label.setText(null);
            }
        }
    }
}
