package mage.game.match;

import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import mage.players.Player;
import org.apache.log4j.Logger;

import java.io.Serializable;

/**
 * @author BetaSteward_at_googlemail.com
 */
public class MatchPlayer implements Serializable {

    private static final Logger logger = Logger.getLogger(MatchPlayer.class);

    private int wins;
    private int winsNeeded;
    private boolean matchWinner;

    private Deck deck;
    private final Player player;
    private final String name;

    private boolean quit;
    private boolean doneSideboarding;
    private int priorityTimeLeft; // keep left time for next game

    public MatchPlayer(Player player, Deck deck, Match match) {
        this.player = player;
        this.deck = deck;
        this.wins = 0;
        this.winsNeeded = match.getWinsNeeded();
        this.doneSideboarding = true;
        this.quit = false;
        this.name = player.getName();
        this.matchWinner = false;
    }

    /**
     * Create match player's copy for simulated/ai games,
     * so game and cards can get access to player's deck
     *
     * @param newPlayer
     * @return
     */
    public MatchPlayer(final MatchPlayer source, Player newPlayer) {
        this.wins = source.wins;
        this.winsNeeded = source.winsNeeded;
        this.matchWinner = source.matchWinner;
        this.deck = source.deck;
        this.player = newPlayer; // new
        this.name = newPlayer.getName(); // new
        this.quit = source.quit;
        this.doneSideboarding = source.doneSideboarding;
        this.priorityTimeLeft = source.priorityTimeLeft;
    }

    public int getPriorityTimeLeft() {
        return priorityTimeLeft;
    }

    public void setPriorityTimeLeft(int priorityTimeLeft) {
        this.priorityTimeLeft = priorityTimeLeft;
    }

    public int getWins() {
        return wins;
    }

    public int getWinsNeeded() {
        return winsNeeded;
    }

    public void addWin() {
        this.wins++;
    }

    public Deck getDeck() {
        return deck;
    }

    public Deck getDeckForViewer() {
        if (this.deck == null) {
            return null;
        }

        // Tiny Leaders uses deck name for game, also must hide real deck name from other players
        Deck viewerDeck = this.deck.copy();
        viewerDeck.setName(this.getName());
        return viewerDeck;
    }

    public void submitDeck(Deck newDeck) {
        this.deck = newDeck;
        this.doneSideboarding = true;
    }

    public boolean updateDeck(Deck newDeck, boolean ignoreMainBasicLands) {
        // used for auto-save by timeout from client side

        // workaround to keep deck name for Tiny Leaders because it must be hidden for players
        if (this.deck != null) {
            newDeck.setName(this.getDeck().getName());
        }

        // make sure it's the same deck (player do not add or remove something)
        boolean isGood = (this.deck.getDeckHash(ignoreMainBasicLands) == newDeck.getDeckHash(ignoreMainBasicLands));
        if (!isGood) {
            logger.error("Found cheating player " + player.getName()
                    + " with changed deck, main " + newDeck.getCards().size() + ", side " + newDeck.getSideboard().size());
            newDeck.getCards().clear();
            newDeck.getSideboard().clear();
        }

        this.deck = newDeck;
        return isGood;
    }

    public Deck autoCompleteDeck(DeckValidator deckValidator) {
        // auto complete deck
        while (deck.getMaindeckCards().size() < deckValidator.getDeckMinSize() && !deck.getSideboard().isEmpty()) {
            Card card = deck.getSideboard().iterator().next();
            deck.getCards().add(card);
            deck.getSideboard().remove(card);
        }
        return deck;
    }

    public Player getPlayer() {
        return player;
    }

    public void setSideboarding() {
        this.doneSideboarding = false;
    }

    public boolean isDoneSideboarding() {
        return this.doneSideboarding;
    }

    public boolean hasQuit() {
        return quit;
    }

    public void setQuit(boolean quit) {
        this.doneSideboarding = true;
        this.quit = quit;
    }

    public boolean isMatchWinner() {
        return matchWinner;
    }

    public void setMatchWinner(boolean matchWinner) {
        this.matchWinner = matchWinner;
    }

    public void cleanUpOnMatchEnd() {
        // Free resources that are not needed after match end
        this.deck = null;
        this.player.cleanUpOnMatchEnd();
        // this.player = null;
    }

    public String getName() {
        return name;
    }

}
