package Server;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Represents the Turn Order tile.
 *
 * Lifecycle per round:
 *  1. At round start, read positions top-to-bottom via nextToPlace() to know
 *     which player places their totem on the offering track first.
 *  2. After a player resolves all their offering actions, they call returnTotem().
 *     returnTotem() places them in the next free slot (top-to-bottom) and
 *     immediately gives them the position reward/penalty.
 *  3. The order in which players called returnTotem() becomes the new turn
 *     order for the NEXT round.
 *  4. resetTrack() is called at the start of each new round to restart the
 *     placement cursor and the return-slot counter, WITHOUT clearing positions
 *     (they already hold the new order from step 2-3).
 */
public class TurnTile {
    private static final Logger logger = LogManager.getLogger(TurnTile.class);
    private final Player[] positions;  // current turn order; updated each round via returnTotem()
    private int nextFreeSlot;          // next available slot for a returning totem
    private int placementCursor;       // cursor used during the totem-placement phase

    public TurnTile(int numP) {
        this.positions    = new Player[numP];
        this.nextFreeSlot  = 0;
        this.placementCursor = 0;
    }

    // -------------------------------------------------------------------------
    // Setup
    // -------------------------------------------------------------------------

    /**
     * Randomises the initial turn order. Call once during game setup.
     */
    public void setInitialOrder(List<Player> players) {

        List<Player> shuffled = new ArrayList<>(players);
        Collections.shuffle(shuffled);
        for (int i = 0; i < shuffled.size(); i++) {
            positions[i] = shuffled.get(i);
        }
        logger.info("setInitialOrder " + this);

    }

    // -------------------------------------------------------------------------
    // Totem-placement phase  (phase 1 of a round)
    // -------------------------------------------------------------------------

    /**
     * Returns the next player who must place their totem on the offering track
     * (following the current turn order, top to bottom).
     * Returns null when all players have already been served this round.
     */
    public Player nextToPlace() {
        if (placementCursor < positions.length) {
            return positions[placementCursor++];
        }
        return null;
    }

    /**
     * Returns the player who is currently expected to place their totem
     * (i.e. the last player returned by nextToPlace), or null if none yet.
     */
    public Player getLastPlacedPlayer() {
        if (placementCursor > 0) {
            return positions[placementCursor - 1];
        }
        return null;
    }


    // -------------------------------------------------------------------------
    // Action-resolution phase  (phase 2 of a round)
    // -------------------------------------------------------------------------

    /**
     * Called when a player has finished resolving all their offering actions.
     * Places the player's totem in the next free slot (determining next-round
     * order) and applies the food reward or penalty for that slot.
     *
     * Reward rules (from the rulebook):
     *  - Slot 0 (first to return): +1 food (2p), +2 food (3-4p), +3 food (5p)
     *  - Slot 1 (second to return, only 4-5 player games): +1 food
     *  - Last slot: pay 1 food; if unable, lose 2 PP instead
     *
     * @return the slot index the player was placed in
     */
    public int returnTotem(Player player) {
        logger.info("returnTotem " + player);
        int slot = nextFreeSlot;

        // --- Position food reward ---
        int positionFood = 0;
        if (slot == 0) {
            positionFood = (positions.length == 2) ? 1
                    : (positions.length == 5) ? 3
                    : 2;  // 3 or 4 players
        } else if (slot == 1 && positions.length >= 4) {
            positionFood = 1;
        }
        player.addFood(positionFood);

        // --- Activate BONUS_FOOD_ENDTURN building if the player has it ---
        // (The building gives +1 extra food whenever the player lands on a food slot)
        BuildingManager.bonusEndTurn(player, positionFood);

        // --- Last-slot penalty ---
        if (slot == positions.length - 1) {
            if (!player.removeFood(1)) {
                player.removePrestigePoints(2);
            }
        }

        positions[slot] = player;
        nextFreeSlot++;

        logger.info(player.getNickname() + " returned totem to slot " + slot
                + (positionFood > 0 ? " and received " + positionFood + " food" : ""));
        return slot;
    }

    public void leaveTurnTile(Player player) {
        for(int i=0;i<positions.length;i++)
            if (positions[i] !=null && positions[i].equals(player)) positions[i]=null;
    }

    // -------------------------------------------------------------------------
    // Round reset
    // -------------------------------------------------------------------------

    /**
     * Resets the cursors for a new round.
     * Does NOT clear positions: those already contain the new turn order
     * established during the previous round's returnTotem() calls.
     */
    public void resetTrack() {
        nextFreeSlot   = 0;
        placementCursor = 0;
    }

    // -------------------------------------------------------------------------
    // Getters
    // -------------------------------------------------------------------------

    /**
     * Returns the full positions array (turn order).
     * Index 0 = first to act, last index = last to act.
     */
    public Player[] getPositions() {
        return positions;
    }

    /** How many players have already returned their totem this round. */
    public int getReturnedCount() {
        return nextFreeSlot;
    }

    @Override
    public String toString() {
        return "TurnTile{" +
                "positions=" + Arrays.toString(positions) +
                '}';
    }
}