//! The error type returned when a tree fails to build.

use std::fmt;

/// A selector that could not be parsed or is not supported.
///
/// Each variant names one failure class. Match on the variant to react, or use
/// the [`fmt::Display`] text to surface the message.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SelectorError {
    /// A pseudo-class outside the supported set.
    ///
    /// Supported names are `empty`, `first-child`, `last-child`, `only-child`,
    /// and `any-link`. `name` is the rejected name without the leading colon.
    UnsupportedPseudoClass {
        /// The rejected pseudo-class name, without the colon.
        name: String,
    },
    /// A selector kind the weave cannot branch on.
    ///
    /// Reached by an unsupported combinator (descendant, `~`, `||`) or a
    /// functional pseudo-class such as `:is()`. `kind` is the internal kind key.
    UnsupportedKind {
        /// The kind key that has no branch.
        kind: String,
    },
    /// A namespace prefix, which the tree does not honor.
    ///
    /// The tree branches on the local name only, so a prefix such as `svg|`
    /// would be dropped and widen the match. Rejected at build time instead.
    /// `prefix` is the rejected prefix, empty for a bare `|name`.
    UnsupportedNamespace {
        /// The rejected namespace prefix, without the `|`.
        prefix: String,
    },
    /// A tokenizer or parser failure.
    ///
    /// `message` carries the full diagnostic, including the caret line.
    Parse {
        /// The diagnostic message.
        message: String,
    },
}

impl fmt::Display for SelectorError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SelectorError::UnsupportedPseudoClass { name } => {
                write!(f, "Unsupported pseudo-class: :{}", name)
            }
            SelectorError::UnsupportedKind { kind } => {
                write!(f, "Unsupported selector kind: {}", kind)
            }
            SelectorError::UnsupportedNamespace { prefix } => {
                write!(f, "Unsupported namespace prefix: {}|", prefix)
            }
            SelectorError::Parse { message } => f.write_str(message),
        }
    }
}

impl std::error::Error for SelectorError {}
