use std::fmt::Debug;

use crate::builder::{ConfigBuilder, DefaultState};
use serde::de::Deserialize;
use serde::ser::Serialize;

use crate::error::{ConfigError, Result};
use crate::map::Map;
use crate::path;
use crate::ser::ConfigSerializer;
use crate::source::Source;
use crate::value::{Table, Value};

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Clone, Debug)]
pub struct Config {
    defaults: Map<path::Expression, Value>,
    overrides: Map<path::Expression, Value>,
    sources: Vec<Box<dyn Source + Send + Sync>>,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            defaults: Default::default(),
            overrides: Default::default(),
            sources: Default::default(),
            cache: Value::new(None, Table::new()),
        }
    }
}

impl Config {
    pub(crate) fn new(value: Value) -> Self {
        Self {
            cache: value,
            ..Self::default()
        }
    }

    /// Creates new [`ConfigBuilder`] instance
    pub fn builder() -> ConfigBuilder<DefaultState> {
        ConfigBuilder::<DefaultState>::default()
    }

    /// Merge in a configuration property source.
    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        self.sources.push(Box::new(source));

        #[allow(deprecated)]
        self.refresh()
    }

    /// Merge in a configuration property source.
    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        self.sources.push(Box::new(source));

        #[allow(deprecated)]
        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn refresh(&mut self) -> Result<&mut Self> {
        self.cache = {
            let mut cache: Value = Map::<String, Value>::new().into();

            // Add defaults
            for (key, val) in &self.defaults {
                key.set(&mut cache, val.clone());
            }

            // Add sources
            self.sources.collect_to(&mut cache)?;

            // Add overrides
            for (key, val) in &self.overrides {
                key.set(&mut cache, val.clone());
            }

            cache
        };

        Ok(self)
    }

    /// Set a default `value` at `key`
    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Self>
    where
        T: Into<Value>,
    {
        self.defaults.insert(key.parse()?, value.into());

        #[allow(deprecated)]
        self.refresh()
    }

    /// Set an overwrite
    ///
    /// This function sets an overwrite value.
    /// The overwrite `value` is written to the `key` location on every `refresh()`
    ///
    /// # Warning
    ///
    /// Errors if config is frozen
    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Self>
    where
        T: Into<Value>,
    {
        self.overrides.insert(key.parse()?, value.into());

        #[allow(deprecated)]
        self.refresh()
    }

    #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
    pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
            **val = value;
        } else {
            expr.set(&mut self.cache, value);
        }
        Ok(())
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_string(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_string)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<Map<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_deserialize' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_deserialize()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<Map<String, Value>> {
        self.cache.clone().into_table()
    }
}
