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

use crate::errors::*;
use crate::mesh_2d::*;

/// Trait for converting between 2D coordinates and linear indices.
///
/// This trait provides bidirectional conversion between 2D `(x, y)` coordinates
/// and 1D linear indices, which is essential for mapping between grid positions
/// and array/vector storage.
///
/// # Coordinate System
///
/// - `x` increases from left to right (column index)
/// - `y` increases from top to bottom (row index)
/// - Linear indices typically follow row-major order: `index = y * width + x`
///
/// # Example
///
/// ```
/// use shortestpath::mesh_2d::{Index2D, Full2D};
///
/// let mesh = Full2D::new(5, 4);
///
/// // Convert (x, y) to linear index
/// let index = mesh.xy_to_index(2, 1).unwrap();
/// assert_eq!(index, 7); // 1 * 5 + 2 = 7
///
/// // Convert back to coordinates
/// let (x, y) = mesh.index_to_xy(7).unwrap();
/// assert_eq!((x, y), (2, 1));
/// ```
pub trait Index2D: Shape2D {
    /// Converts a linear index to 2D coordinates.
    ///
    /// # Arguments
    ///
    /// * `index` - The linear index to convert
    ///
    /// # Returns
    ///
    /// `Ok((x, y))` if the index is valid, or an `Err` if out of bounds
    fn index_to_xy(&self, index: usize) -> Result<(usize, usize)>;

    /// Converts 2D coordinates to a linear index.
    ///
    /// # Arguments
    ///
    /// * `x` - The column coordinate (0-based)
    /// * `y` - The row coordinate (0-based)
    ///
    /// # Returns
    ///
    /// `Ok(index)` if the coordinates are valid, or an `Err` if out of bounds
    fn xy_to_index(&self, x: usize, y: usize) -> Result<usize>;
}
