package eu.jonahbauer.wizard.core.model.card;

import eu.jonahbauer.wizard.common.model.Card;
import eu.jonahbauer.wizard.core.util.Pair;
import lombok.experimental.UtilityClass;

import java.util.Comparator;
import java.util.List;
import java.util.UUID;

@UtilityClass
public class CardUtils {
    public Card.Suit getTrickSuit(List<Pair<UUID, Card>> stack) {
        for (var pair : stack) {
            Card.Suit suit = GameCards.get(pair.second()).getTrickSuit();

            if (suit != null) {
                return suit;
            }
        }

        return Card.Suit.NONE;
    }

    public UUID getWinner(List<Pair<UUID, Card>> stack, Card.Suit trumpSuit) {
        var suit = getTrickSuit(stack);

        Pair<UUID, Card> fairy = null, dragon = null;

        for (Pair<UUID, Card> pair : stack) {
            Card card = pair.second();
            if (card == Card.FAIRY) {
                fairy = pair;
            } else if (card == Card.DRAGON) {
                dragon = pair;
            }
        }

        if (fairy != null && dragon != null) {
            return fairy.first();
        } else if (dragon != null) {
            return dragon.first();
        }

        Comparator<Pair<UUID, Card>> comparator = Comparator.comparingDouble(pair -> {
            GameCard card = GameCards.get(pair.second());
            if (card instanceof WizardCard) {
                return 1000;
            } else if (card instanceof JesterCard) {
                return 0;
            } else if (card == GameCards.BOMB) {
                return -1;
            } else if (card == GameCards.DRAGON) {
                return 2000;
            } else if (card == GameCards.FAIRY) {
                return -1;
            } else if (card instanceof ColoredCard coloredCard) {
                if (coloredCard.getSuit() == trumpSuit) {
                    return 200 + coloredCard.getValue();
                } else if (coloredCard.getSuit() ==  suit) {
                    return 100 + coloredCard.getValue();
                } else {
                    return coloredCard.getValue();
                }
            } else {
                throw new IllegalArgumentException("Dont know how to handle " + pair.second() + ".");
            }
        });

        return stack.stream()
                    .max(comparator)
                    .orElseThrow(() -> new RuntimeException("Could not determine trick winner."))
                    .first();
    }
}
