#![cfg_attr(rustfmt, rustfmt_skip)]
mod constants;
#[cfg(all(unix, not(target_os = "macos")))]
pub(crate) mod message;
#[cfg(all(feature = "images", any(feature = "dbus", feature = "zbus"), unix, not(target_os = "macos")))]
use crate::image::Image;
#[cfg(all(feature = "images", feature = "zbus", unix, not(target_os = "macos")))]
use crate::image::image_spec_str;
use crate::Urgency;
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub enum Hint {
    
    ActionIcons(bool),
    
    
    
    
    Category(String),
    
    
    DesktopEntry(String),
    
    #[cfg(all(feature = "images", unix, not(target_os = "macos")))]
    ImageData(Image),
    
    ImagePath(String),
    
    Resident(bool),
    
    SoundFile(String),
    
    SoundName(String),
    
    SuppressSound(bool),
    
    Transient(bool),
    
    
    X(i32),
    
    
    Y(i32),
    
    Urgency(Urgency),
    
    Custom(String, String),
    
    CustomInt(String, i32),
    
    Invalid 
}
impl Hint {
    
    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            | Hint::ActionIcons(inner)
            | Hint::Resident(inner)
            | Hint::SuppressSound(inner)
            | Hint::Transient(inner) => Some(inner),
            _ => None
        }
    }
    
    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Hint::X(inner) | Hint::Y(inner) => Some(inner),
            _ => None
        }
    }
    
    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Hint::DesktopEntry(ref inner) |
            Hint::ImagePath(ref inner)    |
            Hint::SoundFile(ref inner)    |
            Hint::SoundName(ref inner)    => Some(inner),
            _ => None
        }
    }
    
    pub fn from_key_val(name: &str, value: &str) -> Result<Hint, String> {
        match (name,value){
            (constants::ACTION_ICONS,val)    => val.parse::<bool>().map(Hint::ActionIcons).map_err(|e|e.to_string()),
            (constants::CATEGORY, val)       => Ok(Hint::Category(val.to_owned())),
            (constants::DESKTOP_ENTRY, val)  => Ok(Hint::DesktopEntry(val.to_owned())),
            (constants::IMAGE_PATH, val)     => Ok(Hint::ImagePath(val.to_owned())),
            (constants::RESIDENT, val)       => val.parse::<bool>().map(Hint::Resident).map_err(|e|e.to_string()),
            (constants::SOUND_FILE, val)     => Ok(Hint::SoundFile(val.to_owned())),
            (constants::SOUND_NAME, val)     => Ok(Hint::SoundName(val.to_owned())),
            (constants::SUPPRESS_SOUND, val) => val.parse::<bool>().map(Hint::SuppressSound).map_err(|e|e.to_string()),
            (constants::TRANSIENT, val)      => val.parse::<bool>().map(Hint::Transient).map_err(|e|e.to_string()),
            (constants::X, val)              => val.parse::<i32>().map(Hint::X).map_err(|e|e.to_string()),
            (constants::Y, val)              => val.parse::<i32>().map(Hint::Y).map_err(|e|e.to_string()),
            _                                => Err(String::from("unknown name"))
        }
    }
}
#[cfg(all(unix, not(target_os = "macos")))]
impl Hint {}
#[cfg(all(feature = "zbus", unix, not(target_os = "macos")))]
pub(crate) fn hints_to_map(set: &std::collections::HashSet<Hint>) -> std::collections::HashMap::<&str, zvariant::Value<'_>> {
    set.iter().map(Into::into).collect()
}
#[cfg(all(feature = "zbus", unix, not(target_os = "macos")))]
impl<'a> Into<(&'a str, zvariant::Value<'a>)> for &'a Hint {
    fn into(self) -> (&'a str, zvariant::Value<'a>) {
        use self::constants::*;
        match self {
            Hint::ActionIcons(value)       => (ACTION_ICONS   , zvariant::Value::Bool(*value)), 
            Hint::Category(value)          => (CATEGORY       , zvariant::Value::Str(value.as_str().into())),
            Hint::DesktopEntry(value)      => (DESKTOP_ENTRY  , zvariant::Value::Str(value.as_str().into())),
            #[cfg(all(feature = "zbus", feature = "images", unix, not(target_os = "macos")))]
            
            Hint::ImageData(image)         => (
                image_spec_str(*crate::SPEC_VERSION),
                zvariant::Value::Structure(
                    image.to_tuple().into()
                )
            ),
            Hint::ImagePath(value)         => (IMAGE_PATH     , zvariant::Value::Str(value.as_str().into())),
            Hint::Resident(value)          => (RESIDENT       , zvariant::Value::Bool(*value)), 
            Hint::SoundFile(value)         => (SOUND_FILE     , zvariant::Value::Str(value.as_str().into())),
            Hint::SoundName(value)         => (SOUND_NAME     , zvariant::Value::Str(value.as_str().into())),
            Hint::SuppressSound(value)     => (SUPPRESS_SOUND , zvariant::Value::Bool(*value)),
            Hint::Transient(value)         => (TRANSIENT      , zvariant::Value::Bool(*value)),
            Hint::X(value)                 => (X              , zvariant::Value::I32(*value)),
            Hint::Y(value)                 => (Y              , zvariant::Value::I32(*value)),
            Hint::Urgency(value)           => (URGENCY        , zvariant::Value::U8(*value as u8)),
            Hint::Custom(key, val)         => (key.as_str()   , zvariant::Value::Str(val.as_str().into())),
            Hint::CustomInt(key, val)      => (key.as_str()   , zvariant::Value::I32(*val)),
            Hint::Invalid                  => (INVALID        , zvariant::Value::Str(INVALID.into()))
        }
    }
}
#[cfg(all(feature = "dbus", unix, not(target_os = "macos")))]
impl<'a, A: dbus::arg::RefArg> From<(&'a String, &'a A)> for Hint {
    fn from(pair: (&String, &A)) -> Self {
        let (key, variant) = pair;
        match (key.as_ref(), variant.as_u64(), variant.as_i64(), variant.as_str().map(String::from)) {
            (constants::ACTION_ICONS,   Some(1),  _,       _          ) => Hint::ActionIcons(true),
            (constants::ACTION_ICONS,   _,        _,       _          ) => Hint::ActionIcons(false),
            (constants::URGENCY,        level,    _,       _          ) => Hint::Urgency(level.into()),
            (constants::CATEGORY,       _,        _,       Some(name) ) => Hint::Category(name),
            (constants::DESKTOP_ENTRY,  _,        _,       Some(entry)) => Hint::DesktopEntry(entry),
            (constants::IMAGE_PATH,     _,        _,       Some(path) ) => Hint::ImagePath(path),
            (constants::RESIDENT,       Some(1),  _,       _          ) => Hint::Resident(true),
            (constants::RESIDENT,       _,        _,       _          ) => Hint::Resident(false),
            (constants::SOUND_FILE,     _,        _,       Some(path) ) => Hint::SoundFile(path),
            (constants::SOUND_NAME,     _,        _,       Some(name) ) => Hint::SoundName(name),
            (constants::SUPPRESS_SOUND, Some(1),  _,       _          ) => Hint::SuppressSound(true),
            (constants::SUPPRESS_SOUND, _,        _,       _          ) => Hint::SuppressSound(false),
            (constants::TRANSIENT,      Some(1),  _,       _          ) => Hint::Transient(true),
            (constants::TRANSIENT,      _,        _,       _          ) => Hint::Transient(false),
            (constants::X,              _,        Some(x), _          ) => Hint::X(x as i32),
            (constants::Y,              _,        Some(y), _          ) => Hint::Y(y as i32),
            other => {
                eprintln!("Invalid Hint {:#?} ", other);
                Hint::Invalid
            }
        }
    }
}