use crate::toolbox::matrix::linspace;
use crate::VX;
use std::ops::Index;

/// The time manager
///
/// # Definition
///
/// [`Time`] creates the time vector for the simulation. It is defined by a duration and a time step.
///
/// # Example
///
/// ```
/// use kalast::{DAY, Time};
///
/// let time = Time::new(50. * DAY, 30.); // duration and time step
/// ```
pub struct Time {
    /// The time vector
    pub data: VX<f64>,
}

impl Time {
    /// Time constructor from duration and time step.
    pub fn new(duration: f64, step: f64) -> Self {
        let data = linspace(0., duration, step);
        Self { data }
    }

    /// Get the size of the time vector
    pub fn size(&self) -> usize {
        self.data.len()
    }

    /// Get the duration of the time vector
    pub fn duration(&self) -> f64 {
        self.data[self.size() - 1] - self.data[0]
    }

    /// Get the mean time step from: duration / size
    pub fn time_step(&self) -> f64 {
        self.duration() / (self.size() - 1) as f64
    }

    /// Get the time step between two specific iterations
    pub fn time_step_between(&self, start: usize, end: usize) -> f64 {
        self.data[end] - self.data[start]
    }
}

/// # Accessing data
impl Index<usize> for Time {
    type Output = f64;
    /// To access the time vector from bracket indexing
    fn index<'a>(&'a self, index: usize) -> &'a f64 {
        &self.data[index]
    }
}
