//! Named priority bands for handler registration.
//!
//! Use the named constants (`Priority::BASE`, etc.) for ordering. Within
//! a band, fine-tune with `Priority::BASE.offset(5)`. For unusual values
//! that don't map cleanly to a band, use `Priority::new(v)`.
//! Effective priority for the pipeline is `priority_offset * 1000 + priority.value()`.

#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct Priority(i32);

impl Priority {
    /// Run before base rules — pre-empting overlays (e.g. forced-capture
    /// check that must fire before the base move validator).
    pub const PREEMPT: Self = Self(300);

    /// Override base behaviour — variant rule replaces or supersedes the default.
    pub const OVERRIDE: Self = Self(200);

    /// Secondary constraint — runs after base, refines or adds conditions
    /// (e.g. multi-jump continuation restriction, priority 160).
    pub const SECONDARY: Self = Self(160);

    /// Standard base game rule. Use this for most handlers.
    pub const BASE: Self = Self(100);

    /// Fallback — runs last; fires only if no higher-priority handler handled it.
    pub const FALLBACK: Self = Self(50);

    /// Cleanup / accounting — always runs last; safe for non-game-logic bookkeeping.
    pub const CLEANUP: Self = Self(10);

    /// Construct from a raw value for unusual cases that don't map to a named band.
    /// Prefer the named constants + `.offset(n)` where possible.
    #[inline]
    pub const fn new(v: i32) -> Self { Self(v) }

    /// Fine-tune within a band. Use the named constants for the base value, then
    /// `.offset(n)` to nudge the ordering within that band: `Priority::BASE.offset(5)`.
    /// The offset is `i8` to encourage staying close to a named band.
    #[inline]
    pub const fn offset(self, n: i8) -> Self { Self(self.0 + n as i32) }

    /// Underlying integer value, for arithmetic and pipeline composition.
    #[inline]
    pub const fn value(self) -> i32 { self.0 }
}

impl From<i32> for Priority {
    #[inline]
    fn from(v: i32) -> Self { Self(v) }
}

impl From<Priority> for i32 {
    #[inline]
    fn from(p: Priority) -> i32 { p.0 }
}

/// Legacy alias kept temporarily for backward compatibility. Prefer `Priority`.
pub type PriorityBand = Priority;
