package it.polimi.ingsw.gc14.Model; import it.polimi.ingsw.gc14.Model.Cards.BuildingCard; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType; import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*; import it.polimi.ingsw.gc14.View.TUI.AsciiTable; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static it.polimi.ingsw.gc14.View.TUI.BorderStyle.*; /** * Default Player class; contains all identifiers and methods needed. */ public class Player implements Serializable { /** * The maximum length allowed for the username string. */ private static final int MAX_VALUE = 32; // region Getters /** * Unique string identifier for players; must not be {@code null} and must not * exceed {@link #MAX_VALUE} otherwise an {@link IllegalArgumentException} will be thrown * when the {@link #Player(String) constructor} is called. */ private final String UserName; /** * Getter for the private attribute {@link #UserName}. * @return {@code String} - The UserName */ public String getUserName() { return UserName; } /** * Counts the total {@link it.polimi.ingsw.gc14.Model.Cards.TribeCards.Character Character Cards} * the player currently possesses. * @return {@code int} - Total Character Cards. */ public int getTotCharacters() { return Arrays.stream(CharacterType.values()) .mapToInt(this::getNType) .sum(); } /** * Counts the total number of cards of the specified {@link it.polimi.ingsw.gc14.Model.Cards.TribeCards.CharacterType Character Type}. * Character Type must not be {@code null} * @param type the Character Type to be Counted. * @return {@code int} - Total number of cards of given {@code type}. */ public int getNType(CharacterType type) { return switch (type) { case ARTIST -> artists.size(); case INVENTOR -> inventors.size(); case HUNTER -> hunters.size(); case BUILDER -> builders.size(); case SHAMAN -> shamans.size(); case GATHERER -> gatherers.size(); }; } /** * The List containing all {@link BuildingCard Building Cards} the player currently possesses. */ public ArrayList buildingCards; /** * The List containing all {@link Artist Artist Character Cards} the player currently possesses. */ public ArrayList artists; /** * The List containing all {@link Builder Builder Character Cards} the player currently possesses. */ public ArrayList builders; /** * The List containing all {@link Inventor Inventor Character Cards} the player currently possesses. */ public ArrayList inventors; /** * The List containing all {@link Gatherer Gatherer Character Cards} the player currently possesses. */ public ArrayList gatherers; /** * The List containing all {@link Shaman Shaman Character Cards} the player currently possesses. */ public ArrayList shamans; /** * The List containing all {@link Hunter Hunter Character Cards} the player currently possesses. */ public ArrayList hunters; /** * The current amount of {@code Food} the Player possesses. * Cannot be negative. */ private int FoodValue; /** * Getter for the private attribute {@link #FoodValue}. * @return {@code int} - The amount of Food the player possesses. */ public int getFoodValue() { return FoodValue; } /** * The current amount of {@code Prestige} the Player possesses. */ private int PrestigeValue; /** * Getter for the private attribute {@link #PrestigeValue}. * @return {@code int} - The amount of Prestige the Player possesses. */ public int getPrestigeValue() { return PrestigeValue; } /* TODO * private Game game; * public Game getGame(){ * return Game; * } */ // endregion getters // region Setters /** * Adds {@code Value} amount of {@code Food} to the Player. * @param Value The amount of {@code Food} to be added. * Should be positive for expected results * (otherwise the method will subtract the absolute * value of {@code Value}). * @see #FoodValue */ public void addFood(int Value){ this.FoodValue += Value; } /** * Removes {@code Value} amount of {@code Food} from the Player. * Note: {@link #FoodValue} cannot be negative, so the method will * return {@code False} if {@code Value} is greater than the * amount of {@code Food} the Player possesses, {@code False} otherwise. * @param Value The amount of {@code Food} to be removed. * Should be positive for expected results * (otherwise the method will add the absolute * value of {@code Value}). * @return {@code Boolean} - {@code True} if {@code Value} is greater than * the amount of {@code Food} the Player possesses, {@code False} otherwise. * @see #FoodValue */ public Boolean removeFood(int Value){ if(Value > this.FoodValue){ return false; } this.FoodValue -= Value; return true; } /** * Adds {@code Value} amount of {@code Prestige} to the Player. * @param Value The amount of {@code Prestige} to be added. * Should be positive for expected results * (otherwise the method will subtract the absolute * value of {@code Value}). * @see #PrestigeValue */ public void addPrestige(int Value){ this.PrestigeValue += Value; } /** * Removes {@code Value} amount of {@code Prestige} to the Player. * @param Value The amount of {@code Prestige} to be removed. * Should be positive for expected results * (otherwise the method will add the absolute * value of {@code Value}). * @see #PrestigeValue */ public void removePrestige(int Value){ this.PrestigeValue -= Value; } // endregion setters // region Constructors /** * Constructor for the class {@code Player}. Each Player is uniquely identified by the {@link #UserName}. * @param UserName Unique String identifier for a Player. * @throws IllegalArgumentException When {@code UserName} is {@code null} or exceeds {@link #MAX_VALUE} * with message: *
{@code UserName is empty or exceeds maximum permitted length.}
     *
     * @see #UserName
     * @see #MAX_VALUE
     */
    public Player(String UserName) throws  IllegalArgumentException {
        if(UserName.isEmpty() || UserName.length() > MAX_VALUE) {
            throw new IllegalArgumentException("UserName is empty or exceeds maximum permitted length.");
        }
        this.UserName = UserName;

        this.inventors = new ArrayList <>();
        this.builders = new ArrayList <>();
        this.gatherers = new ArrayList <>();
        this.shamans = new ArrayList <>();
        this.hunters = new ArrayList <>();
        this.artists = new ArrayList<>();

        this.buildingCards = new ArrayList<>();
        this.FoodValue = 0;
        this.PrestigeValue = 0;
    }
    // endregion constructors

    // region Functions
    @Override
    public String toString() {
        int Last = 6;

        var table = new AsciiTable(UNICODE, 1);

        table.addHeader(this.getUserName());
        table.addRow("RESOURCES:");
        table.addRow("Food: " + this.getFoodValue());
        table.addSeparator();
        table.addRow("Prestige: " + this.getPrestigeValue());

        if(!this.hunters.isEmpty()){
            Last = 6;
        }
        else if(!this.inventors.isEmpty()){
            Last = 5;
        }
        else if(!this.shamans.isEmpty()){
            Last = 4;
        }
        else if(!this.gatherers.isEmpty()){
            Last = 3;
        }
        else if(!this.builders.isEmpty()){
            Last = 2;
        }
        else if(!this.artists.isEmpty()){
            Last = 1;
        }
        else{
            Last = 0;
        }

        if(Last == 0){
            table.addSeparator();
        }
        table.addRow("CHARACTERS:");
        if(!this.artists.isEmpty()){
            if(Last == 1){
                table.addSeparator();
            }
            table.addRow("Artists: " + this.artists.toString());
        }

        if(!this.builders.isEmpty()){
            if(Last == 2){
                table.addSeparator();
            }
            table.addRow("Builders: " + this.builders.toString());
        }

        if(!this.gatherers.isEmpty()){
            if(Last == 3){
                table.addSeparator();
            }
            table.addRow("Gatherers: " + this.gatherers.toString());
        }

        if(!this.shamans.isEmpty()){
            if(Last == 4){
                table.addSeparator();
            }
            table.addRow("Shamans: " + this.shamans.toString());
        }

        if(!this.inventors.isEmpty()){
            if(Last == 5){
                table.addSeparator();
            }
            table.addRow("Inventors: " + this.inventors.toString());
        }


        if(!this.hunters.isEmpty()){
            table.addSeparator();
            table.addRow("Hunters: " + this.hunters.toString());
        }

        table.addRow("BUILDING CARDS:");
        if(!this.buildingCards.isEmpty()){
            table.addRow("Buildings: " + this.buildingCards.toString());
        }

        return table.build();
    }
    // endregion functions
}