import { Component, ComponentId, Frozable } from "./Tactic"
import { Pos } from "../../geo/Pos.ts"

export type PlayerId = string

export type PlayerLike = Player | PlayerPhantom

export enum PlayerTeam {
    Allies = "allies",
    Opponents = "opponents",
}

/**
 * All information about a player
 */
export interface PlayerInfo {
    readonly id: ComponentId
    /**
     * the player's team
     * */
    readonly team: PlayerTeam

    /**
     * player's role
     * */
    readonly role: string

    readonly ballState: BallState

    readonly pos: Pos
}

export enum BallState {
    NONE = "NONE",
    HOLDS_ORIGIN = "HOLDS_ORIGIN",
    HOLDS_BY_PASS = "HOLDS_BY_PASS",
    PASSED = "PASSED",
    PASSED_ORIGIN = "PASSED_ORIGIN",
}

export interface Player extends Component<"player", Pos>, PlayerInfo, Frozable {
    readonly path: MovementPath | null
}

export interface MovementPath {
    readonly items: ComponentId[]
}

/**
 * The position of the phantom is known and fixed
 */
export type FixedPhantomPositioning = { type: "fixed" } & Pos
/**
 * The position of the phantom is constrained to a given component.
 * The actual position of the phantom is to determine given its environment.
 */
export type FollowsPhantomPositioning = { type: "follows"; attach: ComponentId }

/**
 * Defines the different kind of positioning a phantom can have
 */
export type PhantomPositioning =
    | FixedPhantomPositioning
    | FollowsPhantomPositioning

/**
 * A player phantom is a kind of component that represents the future state of a player
 * according to the court's step information
 */
export interface PlayerPhantom
    extends Component<"phantom", PhantomPositioning> {
    readonly originPlayerId: ComponentId
    readonly ballState: BallState

    /**
     * Defines a component this phantom will be attached to.
     */
    readonly attachedTo?: ComponentId
}
