/*
    Hurry Curry! - a game about cooking
    Copyright (C) 2026 Hurry Curry! Contributors

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, version 3 of the License only.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

*/

use clap::ValueEnum;
use hurrycurry_protocol::{
    ItemIndex, TileIndex,
    glam::{IVec2, Vec2},
};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum EntityDecl {
    Conveyor {
        from: IVec2,
        to: IVec2,
        speed: Option<f32>,
    },
    ItemPortal {
        from: IVec2,
        to: IVec2,
    },
    PlayerPortal {
        from: Vec2,
        to: Vec2,
    },
    PlayerPortalPair {
        a: IVec2,
        b: IVec2,
        #[serde(default = "default_tile")]
        in_tile: TileIndex,
        #[serde(default = "default_tile")]
        neutral_tile: TileIndex,
        #[serde(default = "default_tile")]
        out_tile: TileIndex,
    },
    Customers {
        scaling_factor: Option<f32>,
        spawn_cooldown: Option<f32>,
        #[serde(default = "default_item")]
        unknown_order: ItemIndex,
    },
    Map {
        name: String,
        pos: Vec2,
    },
    EnvironmentEffect(EnvironmentEffect),
    Environment(Vec<String>),
    Gate {
        condition: GateCondition,
        pos: IVec2,
        blocker_tile: TileIndex,
    },
    Tram {
        length: usize,
        color: Option<i32>,
        points: Vec<Vec2>,
        spacing: f32,
        smoothing: f32,
    },
    Button {
        pos: IVec2,
        action: ButtonAction,
    },
    Pedestrians {
        spawn_delay: f32,
        spawn_delay_stdev: Option<f32>,
        speed: Option<f32>,
        points: Vec<Vec2>,
    },
    TagMinigame {
        #[serde(default = "default_item")]
        tag_item: ItemIndex,
        #[serde(default = "default_tile")]
        blocker_tile: TileIndex,
    },
    DemandSink {
        pos: IVec2,
    },
    CtfMinigame {
        items: Vec<String>,
        spawnpoints: Vec<IVec2>,
        #[serde(default)]
        item_indices: Vec<ItemIndex>,
    },
    Bot {
        name: String,
    },
}

#[derive(Debug, Clone, Copy, Deserialize, Serialize, ValueEnum)]
#[serde(rename_all = "snake_case")]
pub enum ButtonAction {
    Book,
    VoteYes,
    VoteNo,
    MapSelector,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum GateCondition {
    All(Vec<GateCondition>),
    Any(Vec<GateCondition>),
    Stars(String, u8),
}

#[derive(Clone, Debug, Deserialize, Serialize, Default)]
pub struct EnvironmentEffect {
    pub name: String,
    #[serde(default = "default_onoff")]
    pub on: f32,
    #[serde(default)]
    pub on_stdev: f32,
    #[serde(default = "default_onoff")]
    pub off: f32,
    #[serde(default)]
    pub off_stdev: f32,
}
fn default_onoff() -> f32 {
    40.
}
fn default_item() -> ItemIndex {
    ItemIndex(usize::MAX)
}
fn default_tile() -> TileIndex {
    TileIndex(usize::MAX)
}
