package Server;

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

/**
 * Represents a single tile on the offering track.
 *
 * Each tile has a fixed letter (A–G) and a fixed list of actions the
 * occupying player must resolve. The tile is either empty or occupied
 * by exactly one player's totem at any given time.
 *
 * Tile layout (from the rulebook):
 *
 *   Letter │ orderId │ Actions              │ Player count
 *   ───────┼─────────┼──────────────────────┼─────────────
 *     A    │    0    │ FOOD FOOD FOOD        │ 5 only
 *     B    │    1    │ BOTTOM               │ all
 *     C    │    2    │ UP                   │ all
 *     D    │    3    │ BOTTOM BOTTOM        │ 3+
 *     E    │    4    │ BOTTOM UP            │ all
 *     F    │    5    │ UP UP                │ all
 *     G    │    6    │ BOTTOM UP UP         │ 4+
 *
 * Which tiles are included in a game is decided by GameBoard.initOfferingTiles(),
 * not by this class.
 */
public class OfferingTile {

    private static final char FIRST_LETTER = 'A';

    private final int         orderId;
    private final char        letter;
    private final List<Symbol> actions;   // unmodifiable after construction
    private Player            occupant;

    // -------------------------------------------------------------------------
    // Constructor
    // -------------------------------------------------------------------------

    public OfferingTile(int orderId) {
        this.orderId  = orderId;
        this.letter   = (char) (FIRST_LETTER + orderId);
        this.occupant = null;
        this.actions  = Collections.unmodifiableList(buildActions(orderId));
    }

    /**
     * Returns the fixed action list for each tile orderId.
     * Extracted into a private method to keep the constructor clean.
     */
    private static List<Symbol> buildActions(int orderId) {
        List<Symbol> list = new ArrayList<>();
        switch (orderId) {
            case 0:                                                       // A — food tile (5p only)
                list.add(Symbol.FOOD);
                list.add(Symbol.FOOD);
                list.add(Symbol.FOOD);
                break;
            case 1:                                                       // B
                list.add(Symbol.DOWN);
                break;
            case 2:                                                       // C
                list.add(Symbol.UP);
                break;
            case 3:                                                       // D
                list.add(Symbol.DOWN);
                list.add(Symbol.DOWN);
                break;
            case 4:                                                       // E
                list.add(Symbol.DOWN);
                list.add(Symbol.UP);
                break;
            case 5:                                                       // F
                list.add(Symbol.UP);
                list.add(Symbol.UP);
                break;
            case 6:                                                       // G
                list.add(Symbol.DOWN);
                list.add(Symbol.UP);
                list.add(Symbol.UP);
                break;
            default:
                throw new IllegalArgumentException("Invalid OfferingTile orderId: " + orderId);
        }
        return list;
    }

    // -------------------------------------------------------------------------
    // Occupant management
    // -------------------------------------------------------------------------

    /** Returns true if no totem is currently placed on this tile. */
    public boolean isEmpty() {
        return occupant == null;
    }

    /**
     * Places a player's totem on this tile.
     * Callers should check {@link #isEmpty()} before calling this.
     */
    public void setOccupant(Player player) {
        this.occupant = player;
    }

    /**
     * Removes the totem from this tile and returns the player who was on it,
     * or null if the tile was already empty.
     */
    public Player removeOccupant() {
        Player previous = this.occupant;
        this.occupant   = null;
        return previous;
    }

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

    /** The player currently occupying this tile, or null if empty. */
    public Player getOccupant() {
        return occupant;
    }

    /**
     * The actions this tile grants to its occupant (e.g. [BOTTOM, UP]).
     * The returned list is unmodifiable.
     */
    public List<Symbol> getActions() {
        return actions;
    }

    /** 0-based position index; determines the tile's letter and action set. */
    public int getOrderId() {
        return orderId;
    }

    /** The tile's letter label ('A'–'G'), useful for display and logging. */
    public char getLetter() {
        return letter;
    }

    @Override
    public String toString() {
        return "Tile " + letter + " " + actions + (isEmpty() ? " [empty]" : " [" + occupant.getNickname() + "]");
    }
}
