use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Debug;

use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize};

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct Select<T>
where
    T: Selectable,
{
    common: T::CommonType,
    selects: BTreeMap<String, T::SelectsType>,
}

pub trait Selectable
where
    Self: SelectableValue,
{
    type ItemType: SelectableValue;
    type CommonType: SelectableValue + Default;
    type SelectsType: SelectableValue;

    fn is_empty(this: &Select<Self>) -> bool;
    fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>);

    fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)>;
    fn values(this: &Select<Self>) -> Vec<Self::ItemType>;

    fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self>;
}

// Replace with `trait_alias` once stabilized.
// https://github.com/rust-lang/rust/issues/41517
pub trait SelectableValue
where
    Self: Debug + Clone + PartialEq + Eq + Serialize + DeserializeOwned,
{
}

impl<T> SelectableValue for T where T: Debug + Clone + PartialEq + Eq + Serialize + DeserializeOwned {}

// Replace with `trait_alias` once stabilized.
// https://github.com/rust-lang/rust/issues/41517
pub trait SelectableOrderedValue
where
    Self: SelectableValue + PartialOrd + Ord,
{
}

impl<T> SelectableOrderedValue for T where T: SelectableValue + PartialOrd + Ord {}

pub trait SelectableScalar
where
    Self: SelectableValue,
{
}

impl SelectableScalar for String {}
impl SelectableScalar for bool {}
impl SelectableScalar for i64 {}

// General
impl<T> Select<T>
where
    T: Selectable,
{
    pub fn new() -> Self {
        Self {
            common: T::CommonType::default(),
            selects: BTreeMap::new(),
        }
    }

    pub fn from_value(value: T::CommonType) -> Self {
        Self {
            common: value,
            selects: BTreeMap::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        T::is_empty(self)
    }

    pub fn configurations(&self) -> BTreeSet<String> {
        self.selects.keys().cloned().collect()
    }

    pub fn items(&self) -> Vec<(Option<String>, T::ItemType)> {
        T::items(self)
    }

    pub fn values(&self) -> Vec<T::ItemType> {
        T::values(self)
    }

    pub fn insert(&mut self, value: T::ItemType, configuration: Option<String>) {
        T::insert(self, value, configuration);
    }

    pub fn into_parts(self) -> (T::CommonType, BTreeMap<String, T::SelectsType>) {
        (self.common, self.selects)
    }

    pub fn merge(lhs: Self, rhs: Self) -> Self {
        T::merge(lhs, rhs)
    }
}

impl<T> Default for Select<T>
where
    T: Selectable,
{
    fn default() -> Self {
        Self::new()
    }
}

impl<'de, T> Deserialize<'de> for Select<T>
where
    T: Selectable,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Debug, Deserialize)]
        #[serde(untagged)]
        enum Either<T>
        where
            T: Selectable,
        {
            Select {
                common: T::CommonType,
                selects: BTreeMap<String, T::SelectsType>,
            },
            Value(T::CommonType),
        }

        let either = Either::<T>::deserialize(deserializer)?;
        match either {
            Either::Select { common, selects } => Ok(Self { common, selects }),
            Either::Value(common) => Ok(Self {
                common,
                selects: BTreeMap::new(),
            }),
        }
    }
}

// Scalar
impl<T> Selectable for T
where
    T: SelectableScalar,
{
    type ItemType = T;
    type CommonType = Option<Self::ItemType>;
    type SelectsType = Self::ItemType;

    fn is_empty(this: &Select<Self>) -> bool {
        this.common.is_none() && this.selects.is_empty()
    }

    fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> {
        let mut result = Vec::new();
        if let Some(value) = this.common.as_ref() {
            result.push((None, value.clone()));
        }
        result.extend(
            this.selects
                .iter()
                .map(|(configuration, value)| (Some(configuration.clone()), value.clone())),
        );
        result
    }

    fn values(this: &Select<Self>) -> Vec<Self::ItemType> {
        let mut result = Vec::new();
        if let Some(value) = this.common.as_ref() {
            result.push(value.clone());
        }
        result.extend(this.selects.values().cloned());
        result
    }

    fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) {
        match configuration {
            None => {
                this.selects
                    .retain(|_, existing_value| existing_value != &value);
                this.common = Some(value);
            }
            Some(configuration) => {
                if Some(&value) != this.common.as_ref() {
                    this.selects.insert(configuration, value);
                }
            }
        }
    }

    fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> {
        let mut result: Select<Self> = Select::new();

        if let Some(value) = lhs.common {
            result.insert(value, None);
        }
        if let Some(value) = rhs.common {
            result.insert(value, None);
        }

        for (configuration, value) in lhs.selects.into_iter() {
            result.insert(value, Some(configuration));
        }
        for (configuration, value) in rhs.selects.into_iter() {
            result.insert(value, Some(configuration));
        }

        result
    }
}

// Vec<T>
impl<T> Selectable for Vec<T>
where
    T: SelectableValue,
{
    type ItemType = T;
    type CommonType = Vec<T>;
    type SelectsType = Vec<T>;

    fn is_empty(this: &Select<Self>) -> bool {
        this.common.is_empty() && this.selects.is_empty()
    }

    fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> {
        let mut result = Vec::new();
        result.extend(this.common.iter().map(|value| (None, value.clone())));
        result.extend(this.selects.iter().flat_map(|(configuration, values)| {
            values
                .iter()
                .map(|value| (Some(configuration.clone()), value.clone()))
        }));
        result
    }

    fn values(this: &Select<Self>) -> Vec<Self::ItemType> {
        let mut result = Vec::new();
        result.extend(this.common.iter().cloned());
        result.extend(
            this.selects
                .values()
                .flat_map(|values| values.iter().cloned()),
        );
        result
    }

    fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) {
        match configuration {
            None => this.common.push(value),
            Some(configuration) => this.selects.entry(configuration).or_default().push(value),
        }
    }

    fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> {
        let mut result: Select<Self> = Select::new();

        for value in lhs.common.into_iter() {
            result.insert(value, None);
        }
        for value in rhs.common.into_iter() {
            result.insert(value, None);
        }

        for (configuration, values) in lhs.selects.into_iter() {
            for value in values.into_iter() {
                result.insert(value, Some(configuration.clone()));
            }
        }
        for (configuration, values) in rhs.selects.into_iter() {
            for value in values.into_iter() {
                result.insert(value, Some(configuration.clone()));
            }
        }

        result
    }
}

// BTreeSet<T>
impl<T> Selectable for BTreeSet<T>
where
    T: SelectableOrderedValue,
{
    type ItemType = T;
    type CommonType = BTreeSet<T>;
    type SelectsType = BTreeSet<T>;

    fn is_empty(this: &Select<Self>) -> bool {
        this.common.is_empty() && this.selects.is_empty()
    }

    fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> {
        let mut result = Vec::new();
        result.extend(this.common.iter().map(|value| (None, value.clone())));
        result.extend(this.selects.iter().flat_map(|(configuration, values)| {
            values
                .iter()
                .map(|value| (Some(configuration.clone()), value.clone()))
        }));
        result
    }

    fn values(this: &Select<Self>) -> Vec<Self::ItemType> {
        let mut result = Vec::new();
        result.extend(this.common.iter().cloned());
        result.extend(
            this.selects
                .values()
                .flat_map(|values| values.iter().cloned()),
        );
        result
    }

    fn insert(this: &mut Select<Self>, value: Self::ItemType, configuration: Option<String>) {
        match configuration {
            None => {
                this.selects.retain(|_, set| {
                    set.remove(&value);
                    !set.is_empty()
                });
                this.common.insert(value);
            }
            Some(configuration) => {
                if !this.common.contains(&value) {
                    this.selects.entry(configuration).or_default().insert(value);
                }
            }
        }
    }

    fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> {
        let mut result: Select<Self> = Select::new();

        for value in lhs.common.into_iter() {
            result.insert(value, None);
        }
        for value in rhs.common.into_iter() {
            result.insert(value, None);
        }

        for (configuration, values) in lhs.selects.into_iter() {
            for value in values {
                result.insert(value, Some(configuration.clone()));
            }
        }
        for (configuration, values) in rhs.selects.into_iter() {
            for value in values {
                result.insert(value, Some(configuration.clone()));
            }
        }

        result
    }
}

impl<T> Select<BTreeSet<T>>
where
    T: SelectableOrderedValue,
{
    pub fn map<U, F>(self, func: F) -> Select<BTreeSet<U>>
    where
        U: SelectableOrderedValue,
        F: Copy + FnMut(T) -> U,
    {
        Select {
            common: self.common.into_iter().map(func).collect(),
            selects: self
                .selects
                .into_iter()
                .map(|(configuration, values)| {
                    (configuration, values.into_iter().map(func).collect())
                })
                .collect(),
        }
    }
}

// BTreeMap<String, T>
impl<T> Selectable for BTreeMap<String, T>
where
    T: SelectableValue,
{
    type ItemType = (String, T);
    type CommonType = BTreeMap<String, T>;
    type SelectsType = BTreeMap<String, T>;

    fn is_empty(this: &Select<Self>) -> bool {
        this.common.is_empty() && this.selects.is_empty()
    }

    fn items(this: &Select<Self>) -> Vec<(Option<String>, Self::ItemType)> {
        let mut result = Vec::new();
        result.extend(
            this.common
                .iter()
                .map(|(key, value)| (None, (key.clone(), value.clone()))),
        );
        result.extend(this.selects.iter().flat_map(|(configuration, values)| {
            values
                .iter()
                .map(|(key, value)| (Some(configuration.clone()), (key.clone(), value.clone())))
        }));
        result
    }

    fn values(this: &Select<Self>) -> Vec<Self::ItemType> {
        let mut result = Vec::new();
        result.extend(
            this.common
                .iter()
                .map(|(key, value)| (key.clone(), value.clone())),
        );
        result.extend(this.selects.values().flat_map(|values| {
            values
                .iter()
                .map(|(key, value)| (key.clone(), value.clone()))
        }));
        result
    }

    fn insert(
        this: &mut Select<Self>,
        (key, value): Self::ItemType,
        configuration: Option<String>,
    ) {
        match configuration {
            None => {
                this.selects.retain(|_, map| {
                    map.remove(&key);
                    !map.is_empty()
                });
                this.common.insert(key, value);
            }
            Some(configuration) => {
                if !this.common.contains_key(&key) {
                    this.selects
                        .entry(configuration)
                        .or_default()
                        .insert(key, value);
                }
            }
        }
    }

    fn merge(lhs: Select<Self>, rhs: Select<Self>) -> Select<Self> {
        let mut result: Select<Self> = Select::new();

        for (key, value) in lhs.common.into_iter() {
            result.insert((key, value), None);
        }
        for (key, value) in rhs.common.into_iter() {
            result.insert((key, value), None);
        }

        for (configuration, entries) in lhs.selects.into_iter() {
            for (key, value) in entries {
                result.insert((key, value), Some(configuration.clone()));
            }
        }
        for (configuration, entries) in rhs.selects.into_iter() {
            for (key, value) in entries {
                result.insert((key, value), Some(configuration.clone()));
            }
        }

        result
    }
}
