use std::fmt::Display;

use dfir_windows_types::Guid;

use crate::{cache::Value, value::{FromValue, StringOrStringSet, ToStringOrStringSet}, CDatabase};

#[derive(Eq, PartialEq)]
pub struct WellKnownGuid(Guid);

impl FromValue for WellKnownGuid {
    fn from_value_opt(value: &Value) -> crate::ntds::Result<Option<Self>>
    where
        Self: Sized,
    {
        match value {
            Value::Null(_) => Ok(None),
            Value::Binary(v) | Value::Guid(v) => match Guid::from_slice_le(&v[8..]) {
                Ok(guid) => Ok(Some(Self(guid))),
                Err(why) => Err(why.into()),
            },
            v => {
                log::error!("I don't know how to extract GUIDs from {v:?}");
                Ok(None)
            }
        }
    }
}

impl Display for WellKnownGuid {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

impl ToStringOrStringSet for WellKnownGuid
{
    fn to_string_or_stringset(&self, _database: &CDatabase<'_, '_>) -> StringOrStringSet {
        StringOrStringSet::String(self.to_string())
    }
}