use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SyncPreference {
    RrdpThenRsync,
    RsyncOnly,
}

impl Default for SyncPreference {
    fn default() -> Self {
        Self::RrdpThenRsync
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CaFailedFetchPolicy {
    ReuseCurrentInstanceVcir,
    StopAllOutput,
}

impl Default for CaFailedFetchPolicy {
    fn default() -> Self {
        Self::ReuseCurrentInstanceVcir
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SignedObjectFailurePolicy {
    DropObject,
    DropPublicationPoint,
}

impl Default for SignedObjectFailurePolicy {
    fn default() -> Self {
        Self::DropObject
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub struct Policy {
    pub sync_preference: SyncPreference,
    pub ca_failed_fetch_policy: CaFailedFetchPolicy,
    pub signed_object_failure_policy: SignedObjectFailurePolicy,
}

impl Default for Policy {
    fn default() -> Self {
        Self {
            sync_preference: SyncPreference::default(),
            ca_failed_fetch_policy: CaFailedFetchPolicy::default(),
            signed_object_failure_policy: SignedObjectFailurePolicy::default(),
        }
    }
}

#[derive(Debug, thiserror::Error)]
pub enum PolicyParseError {
    #[error("policy TOML parse error: {0}")]
    Toml(String),
}

impl Policy {
    pub fn from_toml_str(s: &str) -> Result<Self, PolicyParseError> {
        toml::from_str(s).map_err(|e| PolicyParseError::Toml(e.to_string()))
    }
}
