// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.

#[derive(Debug, Clone, PartialEq)]
pub enum SAtom {
    Str(String),
    MicroSample(Vec<f32>),
    AudioSample((String, Option<std::sync::Arc<Vec<f32>>>)),
    Setting(i64),
    Param(f32),
}

impl SAtom {
    pub fn str(s: &str) -> Self {
        SAtom::Str(s.to_string())
    }
    pub fn setting(s: i64) -> Self {
        SAtom::Setting(s)
    }
    pub fn param(p: f32) -> Self {
        SAtom::Param(p)
    }
    pub fn micro(m: &[f32]) -> Self {
        SAtom::MicroSample(m.to_vec())
    }
    pub fn audio(s: &str, m: std::sync::Arc<Vec<f32>>) -> Self {
        SAtom::AudioSample((s.to_string(), Some(m)))
    }

    pub fn audio_unloaded(s: &str) -> Self {
        SAtom::AudioSample((s.to_string(), None))
    }

    pub fn default_of(&self) -> Self {
        match self {
            SAtom::Str(_) => SAtom::Str("".to_string()),
            SAtom::MicroSample(_) => SAtom::MicroSample(vec![]),
            SAtom::AudioSample(_) => SAtom::AudioSample(("".to_string(), None)),
            SAtom::Setting(_) => SAtom::Setting(0),
            SAtom::Param(_) => SAtom::Param(0.0),
        }
    }

    pub fn is_continous(&self) -> bool {
        if let SAtom::Param(_) = self {
            true
        } else {
            false
        }
    }

    pub fn i(&self) -> i64 {
        match self {
            SAtom::Setting(i) => *i,
            SAtom::Param(i) => *i as i64,
            _ => 0,
        }
    }

    pub fn s(&self) -> String {
        match self {
            SAtom::Str(s) => s.clone(),
            _ => "".to_string(),
        }
    }

    pub fn f(&self) -> f32 {
        match self {
            SAtom::Setting(i) => *i as f32,
            SAtom::Param(i) => *i,
            _ => 0.0,
        }
    }

    pub fn v_ref(&self) -> Option<&[f32]> {
        match self {
            SAtom::MicroSample(v) => Some(&v[..]),
            SAtom::AudioSample((_, Some(v))) => Some(&v[..]),
            _ => None,
        }
    }

    pub fn type_str(&self) -> &str {
        match self {
            SAtom::Str(_) => "str",
            SAtom::MicroSample(_) => "micro_sample",
            SAtom::AudioSample(_) => "audio_sample",
            SAtom::Setting(_) => "setting",
            SAtom::Param(_) => "param",
        }
    }
}

impl From<f32> for SAtom {
    fn from(n: f32) -> Self {
        SAtom::Param(n)
    }
}
