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

//! Trait for reading 2D cell data from various sources.

use super::cell_type::*;
use crate::errors::*;

/// Trait for reading 2D grid data from various sources.
///
/// This trait provides an abstraction for reading cell types (free/wall)
/// from different data sources such as text, images, or procedural generation.
///
/// # Example
///
/// ```
/// use shortestpath::mesh_source::{Source2D, CellType};
///
/// struct SimpleGrid {
///     width: usize,
///     height: usize,
/// }
///
/// impl Source2D for SimpleGrid {
///     fn get(&self, x: usize, y: usize) -> Result<CellType, shortestpath::Error> {
///         if x >= self.width || y >= self.height {
///             return Err(shortestpath::Error::invalid_xy(x, y));
///         }
///         // Alternating pattern
///         Ok(if (x + y) % 2 == 0 { CellType::FLOOR } else { CellType::WALL })
///     }
///
///     fn width(&self) -> usize { self.width }
///     fn height(&self) -> usize { self.height }
/// }
///
/// let grid = SimpleGrid { width: 4, height: 3 };
/// assert_eq!(grid.get(0, 0).unwrap(), CellType::FLOOR);
/// assert_eq!(grid.get(1, 0).unwrap(), CellType::WALL);
/// ```
pub trait Source2D {
    /// Gets the cell type at the given coordinates.
    ///
    /// # Arguments
    ///
    /// * `x` - The column coordinate (0-based)
    /// * `y` - The row coordinate (0-based)
    ///
    /// # Returns
    ///
    /// The cell type at the given position, or an error if out of bounds.
    fn get(&self, x: usize, y: usize) -> Result<CellType>;

    /// Returns the width (number of columns) of the 2D grid.
    fn width(&self) -> usize;

    /// Returns the height (number of rows) of the 2D grid.
    fn height(&self) -> usize;

    /// Returns the dimensions as a tuple (width, height).
    fn dimensions(&self) -> (usize, usize) {
        (self.width(), self.height())
    }
}
