//! Authoritative resources for the galaxy creation scene.
//!
//! [`GalaxyParams`] is the input to procedural generation; the UI mutates it,
//! the regeneration system detects changes via the `generation` counter, and
//! the generator reads it. [`SelectedStar`] tracks the currently-clicked star.

use bevy::prelude::*;

// ── Tunable defaults ────────────────────────────────────────────────────────
//
// These mirror the docs prototype (`apps/docs/src/prototypes/existing-demos/GalaxyDemo.tsx`)
// so the Bevy scene opens with the same look as the web demo.

const DEFAULT_SEED: u64 = 4242;
const DEFAULT_COUNT: usize = 120;
const DEFAULT_ARMS: u32 = 4;
const DEFAULT_VERTICAL_ARMS: u32 = 0;
const DEFAULT_SIZE: f32 = 280.0;
const DEFAULT_TWIST: f32 = 3.0;
const DEFAULT_VERTICAL_TWIST: f32 = 1.1;

// ── Limits (also mirror the TS sliders) ─────────────────────────────────────

pub const SEED_STEP: u64 = 1;
pub const COUNT_MIN: usize = 40;
pub const COUNT_MAX: usize = 220;
pub const COUNT_STEP: usize = 4;
pub const ARMS_MIN: u32 = 1;
pub const ARMS_MAX: u32 = 6;
/// u32 lower bound is 0; constant kept for symmetry/documentation with the
/// other `*_MIN` bounds.
#[allow(dead_code)]
pub const VERTICAL_ARMS_MIN: u32 = 0;
pub const VERTICAL_ARMS_MAX: u32 = 4;
pub const SIZE_MIN: f32 = 140.0;
pub const SIZE_MAX: f32 = 420.0;
pub const SIZE_STEP: f32 = 10.0;
pub const TWIST_MIN: f32 = 1.0;
pub const TWIST_MAX: f32 = 6.0;
pub const TWIST_STEP: f32 = 0.2;
pub const VERTICAL_TWIST_MIN: f32 = 0.0;
pub const VERTICAL_TWIST_MAX: f32 = 6.0;
pub const VERTICAL_TWIST_STEP: f32 = 0.2;

/// Number of "core" Concord systems clustered at the galactic center.
/// Not exposed in the UI — kept as an internal constant for now.
pub(crate) const CORE_COUNT: usize = 7;

/// Connect each system to its N nearest neighbors (deduplicated).
/// Docs prototype uses 2; kept constant until a UI control is added.
pub(crate) const NEAREST_NEIGHBOR_CONNECTIONS: usize = 2;

/// Max attempts to find a clear spot for each system (Poisson-style spacing).
pub(crate) const SPACING_ATTEMPTS: usize = 180;

/// Procedural galaxy parameters. UI mutates fields, then bumps `generation`
/// to signal the regeneration system to rebuild the scene.
#[derive(Resource, Debug, Clone)]
pub struct GalaxyParams {
    pub seed: u64,
    pub count: usize,
    pub arms: u32,
    pub vertical_arms: u32,
    pub size: f32,
    pub twist: f32,
    pub vertical_twist: f32,
    /// Monotonic counter — any mutation must bump this via [`Self::bump_generation`].
    /// The regeneration system triggers a rebuild whenever this differs from its
    /// last-seen value.
    pub generation: u64,
}

impl Default for GalaxyParams {
    fn default() -> Self {
        Self {
            seed: DEFAULT_SEED,
            count: DEFAULT_COUNT,
            arms: DEFAULT_ARMS,
            vertical_arms: DEFAULT_VERTICAL_ARMS,
            size: DEFAULT_SIZE,
            twist: DEFAULT_TWIST,
            vertical_twist: DEFAULT_VERTICAL_TWIST,
            generation: 0,
        }
    }
}

impl GalaxyParams {
    /// Bump the generation counter, signalling the regeneration system.
    /// Call after any field mutation that should trigger a scene rebuild.
    pub fn bump_generation(&mut self) {
        self.generation = self.generation.wrapping_add(1);
    }

    /// Convenience for the "Regenerate" button: bump the seed and mark dirty.
    pub fn reseed_and_bump(&mut self) {
        self.seed = self.seed.wrapping_add(1);
        self.bump_generation();
    }
}

/// Currently selected star system entity in the galaxy view.
/// `None` means no selection.
#[derive(Resource, Default, Debug, Clone, Copy)]
pub struct SelectedStar(pub Option<Entity>);
