//! Shared models between server and client code.

use serde::Deserialize;
use serde::Serialize;
use std::collections::BTreeMap;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Wall {
    pub rows: u64,
    pub cols: u64,
    pub holds: BTreeMap<HoldPosition, Hold>,
}
impl Wall {
    pub fn new(rows: u64, cols: u64) -> Self {
        let mut holds = BTreeMap::new();
        for row in 0..rows {
            for col in 0..cols {
                let position = HoldPosition { row, col };
                let hold = Hold { position, image: None };
                holds.insert(position, hold);
            }
        }
        Self { rows, cols, holds }
    }
}
impl Default for Wall {
    fn default() -> Self {
        Self::new(12, 12)
    }
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
pub struct HoldPosition {
    /// Starting from 0
    pub row: u64,

    /// Starting from 0
    pub col: u64,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Problem {
    pub holds: BTreeMap<HoldPosition, HoldRole>,
}

/// The role of a hold on a route
#[derive(Serialize, Deserialize, Clone, Debug, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum HoldRole {
    /// Start hold
    Start,

    /// Any hold on the route without a specific role
    Normal,

    /// Zone hold
    Zone,

    /// End hold
    End,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct Hold {
    pub position: HoldPosition,
    pub image: Option<Image>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct Image {
    pub filename: String,
}
