use js_sys::JsString;
use wasm_bindgen::{prelude::*, JsCast};
use crate::{
    local::{Position, RoomName},
    objects::{RoomObject, RoomPosition, Structure},
    prelude::*,
};
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(extends = RoomObject, extends = Structure)]
    #[derive(Clone, Debug)]
    pub type StructurePortal;
    #[wasm_bindgen(method, getter)]
    fn destination_internal(this: &StructurePortal) -> JsValue;
    #[wasm_bindgen(method, getter = ticksToDecay)]
    pub fn ticks_to_decay(this: &StructurePortal) -> u32;
}
impl StructurePortal {
    pub fn destination(&self) -> PortalDestination {
        let dest = Self::destination_internal(self);
        match dest.dyn_ref::<RoomPosition>() {
            Some(room_pos) => PortalDestination::InterRoom(room_pos.into()),
            None => PortalDestination::InterShard(dest.unchecked_into()),
        }
    }
}
impl CanDecay for StructurePortal {
    fn ticks_to_decay(&self) -> u32 {
        Self::ticks_to_decay(self)
    }
}
pub enum PortalDestination {
    InterRoom(Position),
    InterShard(InterShardPortalDestination),
}
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen]
    pub type InterShardPortalDestination;
    #[wasm_bindgen(method, getter = room)]
    fn room_internal(this: &InterShardPortalDestination) -> JsString;
    #[wasm_bindgen(method, getter)]
    pub fn shard(this: &InterShardPortalDestination) -> String;
}
impl InterShardPortalDestination {
    pub fn room(&self) -> RoomName {
        Self::room_internal(self)
            .try_into()
            .expect("expected parseable room name")
    }
}