package game;

import game.map.Castle;

import gui.components.JokerPanel.JokerTypes;

import java.awt.Color;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.stream.Collectors;

public abstract class Player {

    private final String name;
    private Color color;
    private int points;
    private int remainingTroops;
    
    private JokerTypes[] jokers;

    protected Player(String name, Color color) {
        this.name = name;
        this.points = 0;
        this.color = color;
        this.remainingTroops = 0;
        
        jokers = new JokerTypes[]{JokerTypes.ADD_TROOPS, JokerTypes.SCARE_TROOPS};
    }

    public JokerTypes[] getJokers() {
    	return jokers;
    }
    
    public void setJoker(int index, JokerTypes joker) {
    	jokers[index] = joker;
    }
    
    // ?????????????????
    public void setScareTroopsUsed() {
    	jokers[1] = JokerTypes.SCARE_TROOPS_USED;
    }

    /**
     * Creates a player
     * @param playerType The type of player (human, AI, etc.)
     * @param name The name of the player
     * @param color The color of the player
     * @return The new player
     */
    public static Player createPlayer(Class<?> playerType, String name, Color color) {
        if(!Player.class.isAssignableFrom(playerType))
            throw new IllegalArgumentException("Not a player class");

        try {
            Constructor<?> constructor = playerType.getConstructor(String.class, Color.class);
            return (Player) constructor.newInstance(name, color);
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Sets the color of this player
     * @param c
     */
    public void setColor(Color c) {
        this.color = c;
    }

    /**
     * Gets the color of the player
     * @return
     */
    public Color getColor() {
        return this.color;
    }

    /**
     * Gets the name of this player
     * @return The name
     */
    public String getName() {
        return this.name;
    }
    
    public int getRemainingTroops() {
        return this.remainingTroops;
    }

    /**
     * Gets the current points of this player
     * @return The current points
     */
    public int getPoints() {
        return points;
    }

    /**
     * Increases the score of this player
     * @param points The number of points to add
     */
    public void addPoints(int points) {
        this.points += points;
    }

    /**
     * Adds troops to the player
     * @param troops The number of troops to add
     */
    public void addTroops(int troops) {
        if(troops < 0)
            return;

        this.remainingTroops += troops;
    }

    /**
     * Removes troops from this player
     * @param troops The number of troops to remove
     */
    public void removeTroops(int troops) {
        if(this.remainingTroops - troops < 0 || troops < 0)
            return;

        this.remainingTroops -= troops;
    }

    /**
     * Gets the number of castles this player has
     * @param game The game object
     * @return The number of castles
     */
    public int getNumRegions(Game game) {
        return this.getCastles(game).size();
    }

    /**
     * Gets all the castles that belong to the player
     * @param game The game object
     * @return A list of castles
     */
    public List<Castle> getCastles(Game game) {
        return game.getMap().getCastles().stream().filter(c -> c.getOwner() == this).collect(Collectors.toList());
    }

    /**
     * Resets the player by resetting the troops and points
     */
    public void reset() {
        this.remainingTroops = 0;
        this.points = 0;
    }
}
