//! Typed errors returned by the public API. (Spec §6.3.)
//!
//! Every fallible operation returns a `Result`. The library does not
//! panic on invalid input; it returns one of the variants below.

use crate::network::NodeId;

/// Errors that can arise during initial subdivision.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SubdivisionError {
    /// The road graph is not planar at the given node (two roads cross
    /// without a graph node at the crossing point).
    #[error("road graph is not planar at node {0:?}")]
    NonPlanarGraph(NodeId),

    /// A block boundary failed to close into a cycle.
    #[error("block boundary is not closed")]
    OpenBlock,

    /// `SubdivisionParams` failed validation.
    #[error("subdivision parameters invalid: {0}")]
    InvalidParams(String),

    /// A geometric operation (offset, intersection, ...) failed in a
    /// way that suggests degenerate input rather than a bug.
    #[error("geometric operation failed: {0}")]
    GeometryFailure(String),

    /// Reserved for features deferred to a later milestone.
    #[error("feature not yet implemented: {0}")]
    Unimplemented(&'static str),
}

/// Errors returned by `apply_road_edit`.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ParcelError {
    /// The road or node referenced by the edit no longer exists.
    #[error("edit references unknown entity")]
    UnknownEntity,

    /// The edit produced an inconsistent graph; the operation was
    /// rolled back.
    #[error("edit produced inconsistent graph: {0}")]
    InconsistentEdit(String),

    /// Re-subdivision of an affected block failed.
    #[error("re-subdivision after edit failed: {0}")]
    Resubdivide(#[from] SubdivisionError),
}
