package eu.jonahbauer.wizard.client.libgdx.actions.overlay;

import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
import eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings;
import eu.jonahbauer.wizard.client.libgdx.actions.MyActions;
import eu.jonahbauer.wizard.client.libgdx.actors.CardActor;
import eu.jonahbauer.wizard.client.libgdx.screens.GameScreen;
import eu.jonahbauer.wizard.client.libgdx.util.CardUtil;
import eu.jonahbauer.wizard.common.model.Card;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;
import static eu.jonahbauer.wizard.client.libgdx.actions.MyActions.*;
import static eu.jonahbauer.wizard.client.libgdx.screens.GameScreen.*;
import static eu.jonahbauer.wizard.client.libgdx.util.AnimationTimings.OVERLAY_SHARED_ELEMENT;

public class TrumpOverlay extends Overlay {

    private final @Nullable String player;
    private final @Nullable Card card;
    private final @Nullable Card.Suit suit;

    private final @NotNull CardActor trumpCardActor;
    private final @NotNull CardActor trumpSuitActor;

    private boolean animateCard = true;
    private boolean animateSuit = true;

    public TrumpOverlay(@NotNull GameScreen gameScreen, @Nullable String player, @Nullable Card card, @Nullable Card.Suit suit) {
        super(gameScreen, Long.MAX_VALUE);
        this.player = player;
        this.card = card;
        this.suit = suit;
        this.trumpCardActor = Objects.requireNonNull(gameScreen.getTrumpCardActor());
        this.trumpSuitActor = Objects.requireNonNull(gameScreen.getTrumpSuitActor());
    }

    @Override
    public Actor createContent() {
        var root = new VerticalGroup().columnCenter().space(10f);

        String text;

        if (player == null) {
            text = messages.get(suit != null ? switch (suit) {
                case YELLOW -> "game.overlay.trump.yellow";
                case GREEN -> "game.overlay.trump.green";
                case BLUE -> "game.overlay.trump.blue";
                case RED -> "game.overlay.trump.red";
                default -> "game.overlay.trump.none";
            } : "game.overlay.trump.unknown");
        } else {
            text = messages.format(suit != null ? switch (suit) {
                case YELLOW -> "game.overlay.trump.yellow.player";
                case GREEN -> "game.overlay.trump.green.player";
                case BLUE -> "game.overlay.trump.blue.player";
                case RED -> "game.overlay.trump.red.player";
                default -> "game.overlay.trump.none.player";
            } : "game.overlay.trump.unknown.player", player);
        }

        var label = new Label(text, skin);
        label.getStyle().font.getData().markupEnabled = true;
        label.setFontScale(1.5f);
        root.addActor(label);

        var cardGroup = new HorizontalGroup().space(20);
        root.addActor(cardGroup);

        if (trumpCardActor.hasParent() && trumpCardActor.getCard() == card && suit != null) {
            // if card actor is already correct then dont change it
            animateCard = false;
        } else {
            cardGroup.addActor(trumpCardActor);
            trumpCardActor.setCard(card != null ? card : Card.HIDDEN);
        }

        animateSuit = suit != null && suit != CardUtil.getDefaultTrumpSuit(card);
        if (animateSuit) {
            trumpSuitActor.setRotation(0);
            cardGroup.addActor(trumpSuitActor);
            trumpSuitActor.setCard(suit);
        } else {
            trumpSuitActor.remove();
        }

        return root;
    }

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

        boolean cardVisible = trumpCardActor.hasParent();

        var cardAnimation = sequence();

        // remove from parent
        var parallel = parallel();
        if (animateSuit) {
            parallel.addAction(targeting(trumpSuitActor, removeActorSilently()));
        }
        if (animateCard) {
            parallel.addAction(targeting(trumpCardActor, removeActorSilently()));
        }
        cardAnimation.addAction(parallel);

        // change parent in correct order
        parallel = parallel();
        if (animateSuit) {
            parallel.addAction(targeting(trumpSuitActor, changeParent(screen.getOverlayRoot())));
        }
        if (cardVisible) {
            parallel.addAction(targeting(trumpCardActor, changeParent(screen.getOverlayRoot())));
        }
        cardAnimation.addAction(parallel);

        // animate
        parallel = parallel();
        if (animateSuit) {
            parallel.addAction(targeting(trumpSuitActor, rotateTo(TRUMP_SUIT_ROTATION, OVERLAY_SHARED_ELEMENT)));
            parallel.addAction(
                    targeting(trumpSuitActor, moveTo(TRUMP_SUIT_POSITION.x, TRUMP_SUIT_POSITION.y, OVERLAY_SHARED_ELEMENT))
            );
        }
        if (animateCard) {
            parallel.addAction(targeting(trumpCardActor, moveTo(TRUMP_CARD_POSITION.x, TRUMP_CARD_POSITION.y, OVERLAY_SHARED_ELEMENT)));
        }
        cardAnimation.addAction(parallel);

        // change parent in correct order
        parallel = parallel();
        if (animateSuit) {
            parallel.addAction(targeting(trumpSuitActor, changeParent(screen.getContentRoot())));
        }
        if (cardVisible) {
            parallel.addAction(targeting(trumpCardActor, changeParent(screen.getContentRoot())));
        }
        cardAnimation.addAction(parallel);

        var root = getRoot();
        root.addAction(sequence(
                delay(AnimationTimings.OVERLAY_HOLD),
                cardAnimation,
                run(this::close)
        ));
    }

    @Override
    protected void onClosing() {
        var actions = getRoot().getActions();
        if (actions.size > 0) MyActions.finish(actions.get(0));
        onClosed();
    }
}
