mod adjusted;
mod core;
mod full;
mod minimal;

pub use self::core::RealizedCore;
pub use adjusted::AdjustedSopr;
pub use full::{RealizedFull, RealizedFullAccum};
pub use minimal::{RealizedBase, RealizedMinimal};

use brk_error::Result;
use brk_indexer::Lengths;
use vecdb::Exit;

use crate::distribution::state::{CohortState, CostBasisData, RealizedState, WithCapital};

pub trait RealizedLike: Send + Sync {
    fn as_core(&self) -> &RealizedCore;
    fn as_core_mut(&mut self) -> &mut RealizedCore;
    fn min_stateful_len(&self) -> usize;
    fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>);
    fn compute_rest_part1(&mut self, starting_lengths: &Lengths, exit: &Exit) -> Result<()>;
    fn compute_from_stateful(
        &mut self,
        starting_lengths: &Lengths,
        others: &[&RealizedCore],
        exit: &Exit,
    ) -> Result<()>;
}

impl RealizedLike for RealizedCore {
    fn as_core(&self) -> &RealizedCore {
        self
    }
    fn as_core_mut(&mut self) -> &mut RealizedCore {
        self
    }
    fn min_stateful_len(&self) -> usize {
        self.min_stateful_len()
    }
    #[inline(always)]
    fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
        self.push_state(state)
    }
    fn compute_rest_part1(&mut self, starting_lengths: &Lengths, exit: &Exit) -> Result<()> {
        self.compute_rest_part1(starting_lengths, exit)
    }
    fn compute_from_stateful(
        &mut self,
        starting_lengths: &Lengths,
        others: &[&RealizedCore],
        exit: &Exit,
    ) -> Result<()> {
        self.compute_from_stateful(starting_lengths, others, exit)
    }
}

impl RealizedLike for RealizedFull {
    fn as_core(&self) -> &RealizedCore {
        &self.core
    }
    fn as_core_mut(&mut self) -> &mut RealizedCore {
        &mut self.core
    }
    fn min_stateful_len(&self) -> usize {
        self.min_stateful_len()
    }
    #[inline(always)]
    fn push_state(&mut self, state: &CohortState<RealizedState, CostBasisData<WithCapital>>) {
        self.push_state(state)
    }
    fn compute_rest_part1(&mut self, starting_lengths: &Lengths, exit: &Exit) -> Result<()> {
        self.compute_rest_part1(starting_lengths, exit)
    }
    fn compute_from_stateful(
        &mut self,
        starting_lengths: &Lengths,
        others: &[&RealizedCore],
        exit: &Exit,
    ) -> Result<()> {
        self.compute_from_stateful(starting_lengths, others, exit)
    }
}
