use std::error::Error;
use std::fmt::{Debug, Display};
use super::{Direction, Tessellation};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TessellationError {
CoordinateOverflow(usize, usize, Direction),
OffBoard(usize, usize, Direction),
IllegalDirection(Tessellation, Direction),
InvalidDirectionForTile(Tessellation, Direction, usize, usize),
}
impl Error for TessellationError {}
impl Display for TessellationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::CoordinateOverflow(x, y, d) => {
write!(f, "CoordinateOverflow x:{x} y:{y}, d:{d:?}")
}
Self::IllegalDirection(v, d) => {
write!(f, "IllegalDirection {v:?} {d:?}")
}
Self::OffBoard(x, y, d) => {
write!(f, "OffBoard x:{x} y:{y}, d:{d:?}")
}
Self::InvalidDirectionForTile(v, d, x, y) => {
write!(f, "InvalidDirectionForTile {v:?} {d:?} {x} {y}")
}
}
}
}
pub fn validate_and_apply_delta(
x: usize, y: usize, to: Direction, dx: i8, dy: i8, width: usize, height: usize,
) -> Result<(usize, usize), TessellationError> {
if x >= width || y >= height {
return Err(TessellationError::OffBoard(x, y, to));
}
let mut new_x = x;
let mut new_y = y;
if dx == 1 {
if x == usize::MAX {
return Err(TessellationError::CoordinateOverflow(x, y, to));
} else if x >= width {
return Err(TessellationError::OffBoard(x, y, to));
}
new_x += 1;
} else if dx == -1 {
if x == 0 {
return Err(TessellationError::OffBoard(x, y, to));
}
new_x -= 1;
}
if dy == 1 {
if y == usize::MAX {
return Err(TessellationError::CoordinateOverflow(x, y, to));
} else if y >= height {
return Err(TessellationError::OffBoard(x, y, to));
}
new_y += 1;
} else if dy == -1 {
if y == 0 {
return Err(TessellationError::OffBoard(x, y, to));
}
new_y -= 1;
}
if new_x >= width || new_y >= height {
Err(TessellationError::OffBoard(x, y, to))
} else {
Ok((new_x, new_y))
}
}