package eu.jonahbauer.wizard.client.cli.commands;

import eu.jonahbauer.wizard.client.cli.Client;
import eu.jonahbauer.wizard.client.cli.state.Game;
import eu.jonahbauer.wizard.common.messages.client.InteractionMessage;
import eu.jonahbauer.wizard.common.messages.player.JuggleMessage;
import eu.jonahbauer.wizard.common.messages.player.PickTrumpMessage;
import eu.jonahbauer.wizard.common.messages.player.PlayCardMessage;
import eu.jonahbauer.wizard.common.messages.player.PredictMessage;
import eu.jonahbauer.wizard.common.model.Card;
import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.stream.Stream;

import static picocli.CommandLine.*;

@Command(name = "\b", subcommands = {HelpCommand.class, QuitCommand.class, ShowCommand.class})
public class GameCommand {
    private final Client client;

    public GameCommand(Client client) {
        this.client = client;
    }

    @Command(name = "play")
    public void play(
            @Parameters(index = "0", paramLabel = "<card>", completionCandidates = HandCompletion.class) Card card
    ) {
        this.client.send(new InteractionMessage(new PlayCardMessage(card)));
        this.client.waitForReady();
    }

    @Command(name = "predict")
    public void predict(
            @Parameters(index = "0", paramLabel = "<prediction>") int prediction
    ) {
        this.client.send(new InteractionMessage(new PredictMessage(prediction)));
        this.client.waitForReady();
    }

    @Command(name = "trump")
    public void trump(
            @Parameters(index = "0", paramLabel = "<suit>") Card.Suit suit
    ) {
        this.client.send(new InteractionMessage(new PickTrumpMessage(suit)));
        this.client.waitForReady();
    }

    @Command(name = "juggle")
    public void juggle(
            @Parameters(index = "0", paramLabel = "<card>", completionCandidates = JuggleCompletion.class) Card card
    ) {
        this.client.send(new InteractionMessage(new JuggleMessage(card)));
        this.client.waitForReady();
    }

    public static class HandCompletion implements Iterable<String> {
        private final Game game;

        public HandCompletion(Game game) {
            this.game = game;
        }

        @NotNull
        @Override
        public Iterator<String> iterator() {
            return game.getHands().get(game.getSelf()).stream().flatMap(c -> {
                if (c == Card.CLOUD) {
                    return Stream.of(Card.CLOUD_BLUE, Card.CLOUD_GREEN, Card.CLOUD_RED, Card.CLOUD_YELLOW);
                } else if (c == Card.JUGGLER) {
                    return Stream.of(Card.JUGGLER_BLUE, Card.JUGGLER_GREEN, Card.JUGGLER_RED, Card.JUGGLER_YELLOW);
                } else if (c == Card.CHANGELING) {
                    return Stream.of(Card.CHANGELING_JESTER, Card.CHANGELING_WIZARD);
                } else {
                    return Stream.of(c);
                }
            }).map(Card::toString).iterator();
        }
    }

    public static class JuggleCompletion implements Iterable<String> {
        private final Game game;

        public JuggleCompletion(Game game) {
            this.game = game;
        }

        @NotNull
        @Override
        public Iterator<String> iterator() {
            return game.getHands().get(game.getSelf()).stream().map(Card::toString).iterator();
        }
    }
}
