package it.polimi.ingsw.gc14.Model;

import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;

import java.io.Serializable;
import java.util.*;

/**
 * Abstract base class for all order logic cards.
 * An OrderLogicCard manages a queue of players and defines the effects
 * applied when players are pushed back into the queue.
 */
public abstract class OrderLogicCard implements Serializable {

    /**
     * The queue of players associated with this order logic card.
     */
    private Queue<Player> players;

    /**
     * Creates an order logic card with the specified list of players.
     * The input list is shuffled before being inserted into the queue.
     *
     * @param players the list of players associated with this order logic card.
     */
    public OrderLogicCard(ArrayList<Player> players) {
        Collections.shuffle(players);
        this.players = new LinkedList<>(players);
    }

    /**
     * Applies the effect associated with the current queue position of the player
     * and then adds the player to the end of the queue.
     *
     * @param player the player to be pushed into the queue.
     */
    public void push(Player player){
        effect(player,players.size());
        players.add(player);
    }

    /**
     * Removes and returns the first player in the queue.
     *
     * @return the first player in the queue, or {@code null} if the queue is empty.
     */
    public Player pull(){
        return players.poll();
    }

    /**
     * Returns the first player in the queue without removing it.
     *
     * @return the first player in the queue, or {@code null} if the queue is empty.
     */
    public Player getFirst()
    {
        return players.peek();
    }

    /**
     * Applies the effect associated with the specified player and queue position.
     *
     * @param player the player to whom the effect is applied.
     * @param index the queue position index associated with the effect.
     * @throws IndexOutOfBoundsException if the specified index is not valid.
     */
    protected abstract void effect(Player player, int index) throws IndexOutOfBoundsException;

    /**
     * Applies the building-related effect to the specified player.
     * For each building card owned by the player with effect id equal to 3,
     * the player gains 1 Food.
     *
     * @param player the player to whom the building effect is applied.
     */
    protected void buildingEffect(Player player)
    {
        for(BuildingCard b : player.buildingCards.stream().filter(x->x.getEffectId()==3).toList())
            player.addFood(1);
    }
}
