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

import eu.jonahbauer.wizard.common.model.Card;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

import java.util.*;

@UtilityClass
@SuppressWarnings("unused")
public class GameCards {
    private static final Map<Card, GameCard> CARDS = new HashMap<>();

    public final GameCard HIDDEN = register(new NonPlayableCard(Card.HIDDEN, null));
    
    public final GameCard BLUE_1 = register(new ColoredCard(Card.BLUE_1, 1, Card.Suit.BLUE));
    public final GameCard BLUE_2 = register(new ColoredCard(Card.BLUE_2, 2, Card.Suit.BLUE));
    public final GameCard BLUE_3 = register(new ColoredCard(Card.BLUE_3, 3, Card.Suit.BLUE));
    public final GameCard BLUE_4 = register(new ColoredCard(Card.BLUE_4, 4, Card.Suit.BLUE));
    public final GameCard BLUE_5 = register(new ColoredCard(Card.BLUE_5, 5, Card.Suit.BLUE));
    public final GameCard BLUE_6 = register(new ColoredCard(Card.BLUE_6, 6, Card.Suit.BLUE));
    public final GameCard BLUE_7 = register(new ColoredCard(Card.BLUE_7, 7, Card.Suit.BLUE));
    public final GameCard BLUE_8 = register(new ColoredCard(Card.BLUE_8, 8, Card.Suit.BLUE));
    public final GameCard BLUE_9 = register(new ColoredCard(Card.BLUE_9, 9, Card.Suit.BLUE));
    public final GameCard BLUE_10 = register(new ColoredCard(Card.BLUE_10, 10, Card.Suit.BLUE));
    public final GameCard BLUE_11 = register(new ColoredCard(Card.BLUE_11, 11, Card.Suit.BLUE));
    public final GameCard BLUE_12 = register(new ColoredCard(Card.BLUE_12, 12, Card.Suit.BLUE));
    public final GameCard BLUE_13 = register(new ColoredCard(Card.BLUE_13, 13, Card.Suit.BLUE));
    
    public final GameCard RED_1 = register(new ColoredCard(Card.RED_1, 1, Card.Suit.RED));
    public final GameCard RED_2 = register(new ColoredCard(Card.RED_2, 2, Card.Suit.RED));
    public final GameCard RED_3 = register(new ColoredCard(Card.RED_3, 3, Card.Suit.RED));
    public final GameCard RED_4 = register(new ColoredCard(Card.RED_4, 4, Card.Suit.RED));
    public final GameCard RED_5 = register(new ColoredCard(Card.RED_5, 5, Card.Suit.RED));
    public final GameCard RED_6 = register(new ColoredCard(Card.RED_6, 6, Card.Suit.RED));
    public final GameCard RED_7 = register(new ColoredCard(Card.RED_7, 7, Card.Suit.RED));
    public final GameCard RED_8 = register(new ColoredCard(Card.RED_8, 8, Card.Suit.RED));
    public final GameCard RED_9 = register(new ColoredCard(Card.RED_9, 9, Card.Suit.RED));
    public final GameCard RED_10 = register(new ColoredCard(Card.RED_10, 10, Card.Suit.RED));
    public final GameCard RED_11 = register(new ColoredCard(Card.RED_11, 11, Card.Suit.RED));
    public final GameCard RED_12 = register(new ColoredCard(Card.RED_12, 12, Card.Suit.RED));
    public final GameCard RED_13 = register(new ColoredCard(Card.RED_13, 13, Card.Suit.RED));
    
    public final GameCard GREEN_1 = register(new ColoredCard(Card.GREEN_1, 1, Card.Suit.GREEN));
    public final GameCard GREEN_2 = register(new ColoredCard(Card.GREEN_2, 2, Card.Suit.GREEN));
    public final GameCard GREEN_3 = register(new ColoredCard(Card.GREEN_3, 3, Card.Suit.GREEN));
    public final GameCard GREEN_4 = register(new ColoredCard(Card.GREEN_4, 4, Card.Suit.GREEN));
    public final GameCard GREEN_5 = register(new ColoredCard(Card.GREEN_5, 5, Card.Suit.GREEN));
    public final GameCard GREEN_6 = register(new ColoredCard(Card.GREEN_6, 6, Card.Suit.GREEN));
    public final GameCard GREEN_7 = register(new ColoredCard(Card.GREEN_7, 7, Card.Suit.GREEN));
    public final GameCard GREEN_8 = register(new ColoredCard(Card.GREEN_8, 8, Card.Suit.GREEN));
    public final GameCard GREEN_9 = register(new ColoredCard(Card.GREEN_9, 9, Card.Suit.GREEN));
    public final GameCard GREEN_10 = register(new ColoredCard(Card.GREEN_10, 10, Card.Suit.GREEN));
    public final GameCard GREEN_11 = register(new ColoredCard(Card.GREEN_11, 11, Card.Suit.GREEN));
    public final GameCard GREEN_12 = register(new ColoredCard(Card.GREEN_12, 12, Card.Suit.GREEN));
    public final GameCard GREEN_13 = register(new ColoredCard(Card.GREEN_13, 13, Card.Suit.GREEN));
    
    public final GameCard YELLOW_1 = register(new ColoredCard(Card.YELLOW_1, 1, Card.Suit.YELLOW));
    public final GameCard YELLOW_2 = register(new ColoredCard(Card.YELLOW_2, 2, Card.Suit.YELLOW));
    public final GameCard YELLOW_3 = register(new ColoredCard(Card.YELLOW_3, 3, Card.Suit.YELLOW));
    public final GameCard YELLOW_4 = register(new ColoredCard(Card.YELLOW_4, 4, Card.Suit.YELLOW));
    public final GameCard YELLOW_5 = register(new ColoredCard(Card.YELLOW_5, 5, Card.Suit.YELLOW));
    public final GameCard YELLOW_6 = register(new ColoredCard(Card.YELLOW_6, 6, Card.Suit.YELLOW));
    public final GameCard YELLOW_7 = register(new ColoredCard(Card.YELLOW_7, 7, Card.Suit.YELLOW));
    public final GameCard YELLOW_8 = register(new ColoredCard(Card.YELLOW_8, 8, Card.Suit.YELLOW));
    public final GameCard YELLOW_9 = register(new ColoredCard(Card.YELLOW_9, 9, Card.Suit.YELLOW));
    public final GameCard YELLOW_10 = register(new ColoredCard(Card.YELLOW_10, 10, Card.Suit.YELLOW));
    public final GameCard YELLOW_11 = register(new ColoredCard(Card.YELLOW_11, 11, Card.Suit.YELLOW));
    public final GameCard YELLOW_12 = register(new ColoredCard(Card.YELLOW_12, 12, Card.Suit.YELLOW));
    public final GameCard YELLOW_13 = register(new ColoredCard(Card.YELLOW_13, 13, Card.Suit.YELLOW));
    
    public final GameCard BLUE_WIZARD = register(new WizardCard(Card.BLUE_WIZARD));
    public final GameCard RED_WIZARD = register(new WizardCard(Card.RED_WIZARD));
    public final GameCard GREEN_WIZARD = register(new WizardCard(Card.GREEN_WIZARD));
    public final GameCard YELLOW_WIZARD = register(new WizardCard(Card.YELLOW_WIZARD));
    
    public final GameCard BLUE_JESTER = register(new JesterCard(Card.BLUE_JESTER));
    public final GameCard RED_JESTER = register(new JesterCard(Card.RED_JESTER));
    public final GameCard GREEN_JESTER = register(new JesterCard(Card.GREEN_JESTER));
    public final GameCard YELLOW_JESTER = register(new JesterCard(Card.YELLOW_JESTER));

    public final GameCard CHANGELING = register(new NonPlayableCard(Card.CHANGELING, null));
    public final GameCard CHANGELING_WIZARD = register(new ChangelingWizardCard(Card.CHANGELING_WIZARD));
    public final GameCard CHANGELING_JESTER = register(new ChangelingJesterCard(Card.CHANGELING_JESTER));

    public final GameCard BOMB = register(new SimpleCard(Card.BOMB, Card.Suit.NONE, null));
    public final GameCard WEREWOLF = register(new NonPlayableCard(Card.WEREWOLF, null));
    public final GameCard DRAGON = register(new SimpleCard(Card.DRAGON, null, Card.Suit.NONE));
    public final GameCard FAIRY = register(new SimpleCard(Card.FAIRY, Card.Suit.NONE, null));

    public final GameCard CLOUD = register(new NonPlayableCard(Card.CLOUD, null));
    public final GameCard CLOUD_BLUE = register(new ColoredSubcard(Card.CLOUD_BLUE, CLOUD, 9.75, Card.Suit.BLUE));
    public final GameCard CLOUD_RED = register(new ColoredSubcard(Card.CLOUD_RED, CLOUD, 9.75, Card.Suit.RED));
    public final GameCard CLOUD_GREEN = register(new ColoredSubcard(Card.CLOUD_GREEN, CLOUD, 9.75, Card.Suit.GREEN));
    public final GameCard CLOUD_YELLOW = register(new ColoredSubcard(Card.CLOUD_YELLOW, CLOUD, 9.75, Card.Suit.YELLOW));

    public final GameCard JUGGLER = register(new NonPlayableCard(Card.JUGGLER, null));
    public final GameCard JUGGLER_BLUE = register(new ColoredSubcard(Card.JUGGLER_BLUE, JUGGLER, 7.5, Card.Suit.BLUE));
    public final GameCard JUGGLER_RED = register(new ColoredSubcard(Card.JUGGLER_RED, JUGGLER, 7.5, Card.Suit.RED));
    public final GameCard JUGGLER_GREEN = register(new ColoredSubcard(Card.JUGGLER_GREEN, JUGGLER, 7.5, Card.Suit.GREEN));
    public final GameCard JUGGLER_YELLOW = register(new ColoredSubcard(Card.JUGGLER_YELLOW, JUGGLER, 7.5, Card.Suit.YELLOW));

    @Contract("_ -> param1")
    private static GameCard register(@NotNull GameCard card) {        
        if (CARDS.containsKey(card.getCard())) {
            throw new IllegalArgumentException("Name already taken.");
        }
        
        CARDS.put(card.getCard(), card);
        
        return card;
    }

    @NotNull
    public static GameCard get(@NotNull Card name) {
        return CARDS.get(name);
    }

    public static Collection<GameCard> values() {
        return Collections.unmodifiableCollection(CARDS.values());
    }
}
