// Copyright (C) 2025 Christian Mauduit <ufoot@ufoot.org>

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use shortestpath::mesh_2d::Index2D;
use shortestpath::mesh_3d::Index3D;

pub trait Place {
    fn x(&self) -> f32;
    fn y(&self) -> f32;
    fn z(&self) -> f32;
}

#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Place2D {
    x: f32,
    y: f32,
}

impl Place2D {
    pub fn from_index<I: Index2D>(mesh: &I, index: usize) -> Result<Self, shortestpath::Error> {
        let (x_int, y_int) = mesh.index_to_xy(index)?;
        Ok(Self {
            x: x_int as f32 + 0.5,
            y: y_int as f32 + 0.5,
        })
    }
}

impl Place for Place2D {
    fn x(&self) -> f32 {
        self.x
    }

    fn y(&self) -> f32 {
        self.y
    }

    fn z(&self) -> f32 {
        0.5
    }
}

#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Place3D {
    x: f32,
    y: f32,
    z: f32,
}

impl Place3D {
    pub fn from_index<I: Index3D>(mesh: &I, index: usize) -> Result<Self, shortestpath::Error> {
        let (x_int, y_int, z_int) = mesh.index_to_xyz(index)?;
        Ok(Self {
            x: x_int as f32 + 0.5,
            y: y_int as f32 + 0.5,
            z: z_int as f32 + 0.5,
        })
    }
}

impl Place for Place3D {
    fn x(&self) -> f32 {
        self.x
    }

    fn y(&self) -> f32 {
        self.y
    }

    fn z(&self) -> f32 {
        self.z
    }
}
