//! NREL Solar Position Algorithm (SPA) for Rust.
//!
//! Computes the topocentric sun position (zenith, azimuth, elevation),
//! surface incidence angle, equation of time, and sunrise/sunset times
//! from observer location, date/time, and atmospheric conditions.
//!
//! # Quick start
//!
//! ```rust
//! use chrono::Utc;
//! use from_rust_till_dawn::{SpaInput, sun_position};
//!
//! // Detailed control via SpaInput — use Default::default() for fields
//! // you don't need to customise:
//! let out = SpaInput {
//!     year: 2024, month: 6, day: 21,
//!     hour: 12, latitude: 48.8566, longitude: 2.3522,
//!     ..Default::default()
//! }.calculate().unwrap();
//!
//! println!("zenith = {:.2}°, azimuth = {:.2}°", out.zenith, out.azimuth);
//! ```
//!
//! # Reference
//! Reda, I. and Andreas, A. (2004). *Solar Position Algorithm for Solar
//! Radiation Applications*. NREL/TP-560-34302.
#![warn(missing_docs)]

use chrono::{DateTime, Datelike, Timelike, Utc};

pub use spa::{SpaError, SpaInput, SpaOutput, pressure_from_elevation};

mod periodic_terms;
mod spa;

/// Compute the full solar position from a UTC timestamp and observer parameters.
///
/// This is a convenience wrapper around [`SpaInput::calculate`]. It always
/// computes zenith/azimuth, surface incidence angle, and RTS (rise/transit/set).
///
/// `pressure` — atmospheric pressure in mbar; `None` estimates it from `elevation`.
#[must_use = "the computed solar position is unused"]
pub fn spa(
    time: &DateTime<Utc>,
    delta_ut1: f64,
    delta_t: f64,
    timezone: f64,
    longitude: f64,
    latitude: f64,
    elevation: f64,
    pressure: Option<f64>,
    temperature: f64,
    slope: f64,
    azm_rotation: f64,
    atmos_refract: f64,
) -> Result<SpaOutput, SpaError> {
    SpaInput {
        year: time.year(),
        month: time.month() as i32,
        day: time.day() as i32,
        hour: time.hour() as i32,
        minute: time.minute() as i32,
        second: time.second() as f64,
        delta_ut1,
        delta_t,
        timezone,
        longitude,
        latitude,
        elevation,
        pressure,
        temperature,
        slope,
        azm_rotation,
        atmos_refract,
    }
    .calculate()
}

/// Compute sun position using standard defaults for correction and atmospheric parameters.
///
/// Suitable for quick lookups where high precision is not required. Uses
/// ΔT = 69 s, zero UT1 correction, and NREL standard atmospheric refraction.
/// For full control use [`SpaInput`] directly.
#[must_use = "the computed solar position is unused"]
pub fn sun_position(
    time: &DateTime<Utc>,
    latitude: f64,
    longitude: f64,
    elevation: f64,
    pressure: Option<f64>,
    temperature: f64,
) -> Result<SpaOutput, SpaError> {
    SpaInput {
        year: time.year(),
        month: time.month() as i32,
        day: time.day() as i32,
        hour: time.hour() as i32,
        minute: time.minute() as i32,
        second: time.second() as f64,
        delta_t: 69.0,
        longitude,
        latitude,
        elevation,
        pressure,
        temperature,
        ..Default::default()
    }
    .calculate()
}
