use crate::core::calendar::solar_to_lunar;
use crate::core::error::ChartError;
use crate::core::model::calendar::{BirthTime, SolarDay, SolarMonth};
use crate::core::model::chart::{
Chart, TemporalPalaceLayout,
temporal_layout::{build_life_branch_palace_layout, monthly_palace_index},
};
use crate::core::model::ganzhi::{EarthlyBranch, StemBranch};
use crate::core::model::star::mutagen::Scope;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct MonthlyPeriod {
index: usize,
lunar_month: u8,
stem_branch: StemBranch,
palace_branch: EarthlyBranch,
palace_layout: TemporalPalaceLayout,
}
impl MonthlyPeriod {
fn new(
index: usize,
lunar_month: u8,
stem_branch: StemBranch,
palace_branch: EarthlyBranch,
palace_layout: TemporalPalaceLayout,
) -> Self {
Self {
index,
lunar_month,
stem_branch,
palace_branch,
palace_layout,
}
}
pub const fn index(&self) -> usize {
self.index
}
pub const fn lunar_month(&self) -> u8 {
self.lunar_month
}
pub const fn stem_branch(&self) -> StemBranch {
self.stem_branch
}
pub const fn palace_branch(&self) -> EarthlyBranch {
self.palace_branch
}
pub const fn palace_layout(&self) -> &TemporalPalaceLayout {
&self.palace_layout
}
}
pub fn build_monthly_period(
natal: &Chart,
target_solar_year: i32,
target_solar_month: SolarMonth,
target_solar_day: SolarDay,
target_time: BirthTime,
) -> Result<MonthlyPeriod, ChartError> {
let conversion = solar_to_lunar(
target_solar_year,
target_solar_month,
target_solar_day,
target_time.iztro_time_index(),
)?;
let index = monthly_palace_index(
natal,
conversion.lunar_year(),
conversion.lunar_month().value(),
conversion.lunar_day().value(),
conversion.is_leap_month(),
);
let palace_branch = EarthlyBranch::Yin.offset(index as isize);
let palace_layout = build_life_branch_palace_layout(Scope::Monthly, palace_branch)?;
Ok(MonthlyPeriod::new(
index,
conversion.lunar_month().value(),
conversion.four_pillars().monthly,
palace_branch,
palace_layout,
))
}