//! `game-wasm` — REIKHELM: DESCENT's browser bridge.
//!
//! The run logic lives in [`run::GameRun`] (pure Rust, natively tested); this
//! crate face is a thin `wasm-bindgen` wrapper in the same style as
//! `combat-wasm`: JSON strings in and out, every mutating call returning the
//! fresh state payload so the front-end re-renders from one source of truth.

pub mod manifest;
pub mod monster_ai;
pub mod run;
pub mod spawn;
pub mod views;

use run::GameRun;
use wasm_bindgen::prelude::*;

/// A live run the browser drives.
#[wasm_bindgen]
pub struct Game {
    run: GameRun,
}

#[wasm_bindgen]
impl Game {
    /// Start a run: `manifests_json` is a JSON array of atlas manifests in
    /// floor order (fetched by the page from /out/atlas/<seed>/manifest.json),
    /// `archetype` the player stat-block id, `seed` the run seed.
    #[wasm_bindgen(constructor)]
    pub fn new(
        config_json: &str,
        manifests_json: &str,
        archetype: &str,
        seed: u64,
    ) -> Result<Game, JsValue> {
        GameRun::new(config_json, manifests_json, archetype, seed)
            .map(|run| Game { run })
            .map_err(|e| JsValue::from_str(&e))
    }

    /// Current state without advancing (initial render).
    pub fn state(&mut self) -> String {
        self.run.state_json()
    }

    /// Rotate facing by `delta` quarter-turns (+1 = right).
    pub fn turn(&mut self, delta: i32) -> String {
        self.run.turn(delta);
        self.run.state_json()
    }

    /// Step to the adjacent room ahead (or behind when `forward` is false).
    pub fn step(&mut self, forward: bool) -> String {
        self.run.step(forward);
        self.run.state_json()
    }

    /// Take the stairs down (only at the exit room, in explore mode).
    pub fn descend(&mut self) -> String {
        self.run.descend();
        self.run.state_json()
    }

    /// Catch your breath without moving (hold to keep resting).
    pub fn rest(&mut self) -> String {
        self.run.rest();
        self.run.state_json()
    }

    /// Drink a potion: `kind` is `"draught"` or `"tonic"`.
    #[wasm_bindgen(js_name = useItem)]
    pub fn use_item(&mut self, kind: &str) -> String {
        self.run.use_item(kind);
        self.run.state_json()
    }

    /// Advance the battle one tick (call at the config tick rate).
    #[wasm_bindgen(js_name = combatTick)]
    pub fn combat_tick(&mut self) -> String {
        self.run.combat_tick();
        self.run.state_json()
    }

    /// Queue an ability for the next combat decision. `target < 0` picks a
    /// sensible default.
    #[wasm_bindgen(js_name = useAbility)]
    pub fn use_ability(&mut self, ability_id: &str, target: i32) {
        self.run.use_ability(ability_id, target);
    }

    /// Toggle the passive swing.
    #[wasm_bindgen(js_name = setAutoAttack)]
    pub fn set_auto_attack(&mut self, on: bool) {
        self.run.set_auto_attack(on);
    }

    /// Focus a specific enemy actor id.
    #[wasm_bindgen(js_name = setTarget)]
    pub fn set_target(&mut self, target: u32) {
        self.run.set_target(target);
    }

    /// Break off the current fight (costs fatigue, returns to the previous room).
    pub fn flee(&mut self) -> String {
        self.run.flee();
        self.run.state_json()
    }

    /// The player's slotted abilities (action bar), as JSON.
    pub fn abilities(&self) -> String {
        views::abilities_json(&self.run)
    }
}
