use std::fmt;
pub enum Compatibility {
        AT = 0,
        V1,
        V2,
}
pub(crate) use windows::Win32::System::TaskScheduler::TASK_COMPATIBILITY;
impl From<Compatibility> for TASK_COMPATIBILITY {
    fn from(item: Compatibility) -> Self {
        TASK_COMPATIBILITY(item as i32)
    }
}
#[allow(deprecated)]
pub struct IdleSettings {
    #[deprecated]
                        pub idle_duration: Option<Duration>,
            pub restart_on_idle: Option<bool>,
            pub stop_on_idle_end: Option<bool>,
    #[deprecated]
                    pub wait_timeout: Option<Duration>,
}
#[allow(deprecated)]
impl IdleSettings {
        pub fn new() -> IdleSettings {
        IdleSettings {
            idle_duration: None,
            restart_on_idle: None,
            stop_on_idle_end: None,
            wait_timeout: None,
        }
    }
}
impl Default for IdleSettings {
    fn default() -> Self {
        Self::new()
    }
}
pub enum InstancesPolicy {
        Parallel = 0,
        Queue,
        IgnoreNew,
        StopExisting,
}
pub(crate) use windows::Win32::System::TaskScheduler::TASK_INSTANCES_POLICY;
impl From<InstancesPolicy> for TASK_INSTANCES_POLICY {
    fn from(item: InstancesPolicy) -> Self {
        TASK_INSTANCES_POLICY(item as i32)
    }
}
pub enum LogonType {
        None = 0,
        Password,
                S4U,
        InteractiveToken,
        Group,
            ServiceAccount,
                InteractiveTokenOrPassword,
}
pub struct NetworkSettings {
        pub id: String,
        pub name: String,
}
pub struct PrincipalSettings {
        pub display_name: String,
            pub group_id: Option<String>,
        pub id: String,
            pub logon_type: LogonType,
            pub run_level: RunLevel,
            pub user_id: Option<String>,
}
pub enum RunLevel {
        Highest = 1,
        LUA = 0,
}
pub struct Settings {
            pub allow_demand_start: Option<bool>,
        pub allow_hard_terminate: Option<bool>,
        pub compatibility: Option<Compatibility>,
        pub delete_expired_task_after: Option<Duration>,
            pub disallow_start_if_on_batteries: Option<bool>,
            pub enabled: Option<bool>,
        pub execution_time_limit: Option<String>,
            pub hidden: Option<bool>,
        pub idle_settings: Option<IdleSettings>,
        pub multiple_instances_policy: Option<InstancesPolicy>,
                    pub network_settings: Option<NetworkSettings>,
        pub priority: Option<i32>,
        pub restart_count: Option<i32>,
        pub restart_interval: Option<String>,
            pub run_only_if_idle: Option<bool>,
            pub run_only_if_network_available: Option<bool>,
            pub start_when_available: Option<bool>,
            pub stop_if_going_on_batteries: Option<bool>,
            pub wake_to_run: Option<bool>,
        pub xml_text: Option<String>,
}
impl Settings {
        pub fn new() -> Settings {
        Settings {
            allow_demand_start: None,
            allow_hard_terminate: None,
            compatibility: None,
            delete_expired_task_after: None,
            disallow_start_if_on_batteries: None,
            enabled: None,
            execution_time_limit: None,
            hidden: None,
            idle_settings: None,
            multiple_instances_policy: None,
            network_settings: None,
            priority: None,
            restart_count: None,
            restart_interval: None,
            run_only_if_idle: None,
            run_only_if_network_available: None,
            start_when_available: None,
            stop_if_going_on_batteries: None,
            wake_to_run: None,
            xml_text: None,
        }
    }
}
impl Default for Settings {
    fn default() -> Self {
        Self::new()
    }
}
#[derive(Debug, Clone, Copy)]
#[allow(missing_docs)]
pub struct Duration {
    pub days: Option<usize>,
    pub hours: Option<usize>,
    pub minutes: Option<usize>,
    pub months: Option<usize>,
    pub seconds: Option<usize>,
    pub years: Option<usize>,
}
impl Duration {
        pub fn new() -> Duration {
        Duration {
            days: None,
            hours: None,
            minutes: None,
            months: None,
            seconds: None,
            years: None,
        }
    }
}
macro_rules! format_duration {
    ($str:expr, $num:expr, $code:literal) => {
        if let Some(num) = $num {
            if num > 0 {
                $str = format!("{}{}{}", $str, num, $code);
            }
        }
    };
}
impl fmt::Display for Duration {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s = String::new();
                        format_duration!(s, self.years, "Y");
        format_duration!(s, self.months, "M");
        format_duration!(s, self.days, "D");
        if self.hours.is_some() || self.minutes.is_some() || self.hours.is_some() {
            s = format!("{}T", s);
            format_duration!(s, self.hours, "H");
            format_duration!(s, self.minutes, "M");
            format_duration!(s, self.seconds, "S");
        }
        if s.is_empty() {
            return write!(f, "")
        }
        write!(f, "P{}", s)
    }
}
impl Default for Duration {
    fn default() -> Self {
        Self::new()
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn macro_test() {
        let mut s = String::new();
        format_duration!(s, Some(2), "Y");
        format_duration!(s, Some(1), "D");
        assert_eq!(s, "2Y1D");
    }
    #[test]
    fn duration_all_set() {
        let d = Duration {
            years: Some(1),
            months: Some(2),
            days: Some(3),
            hours: Some(4),
            minutes: Some(5),
            seconds: Some(6),
        };
        assert_eq!("P1Y2M3DT4H5M6S", d.to_string());
    }
    #[test]
    fn duration_time_only() {
        let mut d = Duration::new();
        d.hours = Some(1);
        d.minutes = Some(2);
        d.seconds = Some(3);
        assert_eq!("PT1H2M3S", d.to_string());
    }
    
    #[test]
    fn duration_zero_year_removed() {
        let mut d = Duration::new();
        d.years = Some(0);
        assert_eq!("", d.to_string());
    }
}