// auto-generated by: jiff-cli generate shared

use crate::shared::{
    error,
    util::itime::{days_in_month, days_in_year, IEpochDay},
};

// N.B. Every variant in this error type is a range error.
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum Error {
    DateInvalidDayOfYear { year: i16 },
    DateInvalidDayOfYearNoLeap,
    DateInvalidDays { year: i16, month: i8 },
    DateTimeSeconds,
    // TODO: I believe this can never happen.
    DayOfYear,
    EpochDayDays,
    EpochDayI32,
    NthWeekdayOfMonth,
    Tomorrow,
    YearNext,
    YearPrevious,
    Yesterday,
}

impl From<Error> for error::Error {
    #[cold]
    #[inline(never)]
    fn from(err: Error) -> error::Error {
        error::ErrorKind::Time(err).into()
    }
}

// impl error::IntoError for Error {
// fn into_error(self) -> error::Error {
// self.into()
// }
// }

impl core::fmt::Display for Error {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        use self::Error::*;

        match *self {
            DateInvalidDayOfYear { year } => write!(
                f,
                "number of days for `{year:04}` is invalid, \
                 must be in range `1..={max_day}`",
                max_day = days_in_year(year),
            ),
            DateInvalidDayOfYearNoLeap => f.write_str(
                "number of days is invalid, must be in range `1..=365`",
            ),
            DateInvalidDays { year, month } => write!(
                f,
                "number of days for `{year:04}-{month:02}` is invalid, \
                 must be in range `1..={max_day}`",
                max_day = days_in_month(year, month),
            ),
            DateTimeSeconds => {
                f.write_str("adding seconds to datetime overflowed")
            }
            DayOfYear => f.write_str("day of year is invalid"),
            EpochDayDays => write!(
                f,
                "adding to epoch day resulted in a value outside \
                 the allowed range of `{min}..={max}`",
                min = IEpochDay::MIN.epoch_day,
                max = IEpochDay::MAX.epoch_day,
            ),
            EpochDayI32 => f.write_str(
                "adding to epoch day overflowed 32-bit signed integer",
            ),
            NthWeekdayOfMonth => f.write_str(
                "invalid nth weekday of month, \
                 must be non-zero and in range `-5..=5`",
            ),
            Tomorrow => f.write_str(
                "returning tomorrow for `9999-12-31` is not \
                 possible because it is greater than Jiff's supported
                 maximum date",
            ),
            YearNext => f.write_str(
                "creating a date for a year following `9999` is \
                 not possible because it is greater than Jiff's supported \
                 maximum date",
            ),
            YearPrevious => f.write_str(
                "creating a date for a year preceding `-9999` is \
                 not possible because it is less than Jiff's supported \
                 minimum date",
            ),
            Yesterday => f.write_str(
                "returning yesterday for `-9999-01-01` is not \
                 possible because it is less than Jiff's supported
                 minimum date",
            ),
        }
    }
}
