use lunar_rust::lunar::LunarRefHelper;
use lunar_rust::lunar_month::{self, LunarMonthRefHelper};
use lunar_rust::{lunar, solar};
use crate::astro::builder::{branch_of, fix_lunar_month_index, stem_of};
use crate::astro::palace::{SoulAndBody, get_five_elements_class, get_soul_and_body};
use crate::data::types::*;
use crate::error::IztroError;
pub struct AstroContext {
pub effective_time_index: u8,
pub lunar_day: u32,
pub lunar_month: u32,
pub is_leap: bool,
pub month_day_count: u32,
pub yearly_stem: HeavenlyStem,
pub yearly_branch: EarthlyBranch,
pub flow_yearly_stem: HeavenlyStem,
pub flow_yearly_branch: EarthlyBranch,
pub month_index: usize,
pub soul_body: SoulAndBody,
pub five_elements_class: FiveElementsClass,
}
pub fn derive(
solar_date: &str,
time_index: u8,
fix_leap: bool,
config: &Config,
) -> Result<AstroContext, IztroError> {
crate::astro::builder::validate_time_index(time_index)?;
let (year, month, day) = crate::astro::builder::parse_solar_date(solar_date)?;
let effective_time_index = if config.day_divide == DayDivide::Current && time_index >= 12 {
0
} else {
time_index
};
let hour = crate::astro::builder::time_index_to_hour(effective_time_index);
let solar_with_time = solar::from_ymdhms(year, month, day, hour, 0, 0);
let lunar_ref = lunar::from_solar(&solar_with_time);
let lunar_month_raw = lunar_ref.get_month(); let is_leap = lunar_month_raw < 0;
let lunar_month = lunar_month_raw.unsigned_abs() as u32;
let lunar_day = lunar_ref.get_day() as u32;
let (yearly_stem_str, yearly_branch_str) = match config.year_divide {
YearDivide::Normal => (lunar_ref.get_year_gan(), lunar_ref.get_year_zhi()),
YearDivide::Exact => (
lunar_ref.get_year_gan_by_li_chun(),
lunar_ref.get_year_zhi_by_li_chun(),
),
};
let yearly_stem = stem_of(&yearly_stem_str, "birth year")?;
let yearly_branch = branch_of(&yearly_branch_str, "birth year")?;
let (flow_stem_str, flow_branch_str) = match config.horoscope_divide {
HoroscopeDivide::Normal => (lunar_ref.get_year_gan(), lunar_ref.get_year_zhi()),
HoroscopeDivide::Exact => (
lunar_ref.get_year_gan_by_li_chun(),
lunar_ref.get_year_zhi_by_li_chun(),
),
};
let flow_yearly_stem = stem_of(&flow_stem_str, "flow year")?;
let flow_yearly_branch = branch_of(&flow_branch_str, "flow year")?;
let month_index = fix_lunar_month_index(
lunar_month,
lunar_day,
is_leap,
effective_time_index,
fix_leap,
);
let soul_body = get_soul_and_body(month_index, effective_time_index, yearly_stem);
let five_elements_class = get_five_elements_class(
soul_body.heavenly_stem_of_soul,
soul_body.earthly_branch_of_soul,
);
let month_day_count =
lunar_month::from_ym(lunar_ref.get_year(), lunar_month_raw).get_day_count() as u32;
Ok(AstroContext {
effective_time_index,
lunar_day,
lunar_month,
is_leap,
month_day_count,
yearly_stem,
yearly_branch,
flow_yearly_stem,
flow_yearly_branch,
month_index,
soul_body,
five_elements_class,
})
}