use crate::expr::Expression;
use crate::{Decor, Decorate, Decorated, Ident, RawString, Span};
use std::ops::{self, Range};
use vecmap::map::{MutableKeys, VecMap};
pub type ObjectIntoIter = Box<dyn Iterator<Item = (ObjectKey, ObjectValue)>>;
pub type ObjectIter<'a> = Box<dyn Iterator<Item = (&'a ObjectKey, &'a ObjectValue)> + 'a>;
pub type ObjectIterMut<'a> = Box<dyn Iterator<Item = (ObjectKeyMut<'a>, &'a mut ObjectValue)> + 'a>;
#[derive(Debug, Clone, Eq, Default)]
pub struct Object {
    items: VecMap<ObjectKey, ObjectValue>,
    trailing: RawString,
    decor: Decor,
    span: Option<Range<usize>>,
}
impl Object {
    #[inline]
    pub fn new() -> Self {
        Object::default()
    }
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Object {
            items: VecMap::with_capacity(capacity),
            ..Default::default()
        }
    }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.items.is_empty()
    }
    #[inline]
    pub fn len(&self) -> usize {
        self.items.len()
    }
    #[inline]
    pub fn clear(&mut self) {
        self.items.clear();
    }
    #[inline]
    pub fn contains_key(&self, key: &ObjectKey) -> bool {
        self.items.contains_key(key)
    }
    #[inline]
    pub fn get(&self, key: &ObjectKey) -> Option<&ObjectValue> {
        self.items.get(key)
    }
    #[inline]
    pub fn get_mut(&mut self, key: &ObjectKey) -> Option<&mut ObjectValue> {
        self.items.get_mut(key)
    }
    #[inline]
    pub fn get_key_value(&self, key: &ObjectKey) -> Option<(&ObjectKey, &ObjectValue)> {
        self.items.get_key_value(key)
    }
    #[inline]
    pub fn get_key_value_mut<'a>(
        &'a mut self,
        key: &ObjectKey,
    ) -> Option<(ObjectKeyMut<'a>, &'a mut ObjectValue)> {
        self.items
            .get_full_mut2(key)
            .map(|(_, k, v)| (ObjectKeyMut::new(k), v))
    }
    #[inline]
    pub fn insert(
        &mut self,
        key: impl Into<ObjectKey>,
        value: impl Into<ObjectValue>,
    ) -> Option<ObjectValue> {
        self.items.insert(key.into(), value.into())
    }
    #[inline]
    pub fn remove(&mut self, key: &ObjectKey) -> Option<ObjectValue> {
        self.items.remove(key)
    }
    #[inline]
    pub fn remove_entry(&mut self, key: &ObjectKey) -> Option<(ObjectKey, ObjectValue)> {
        self.items.remove_entry(key)
    }
    #[inline]
    pub fn iter(&self) -> ObjectIter<'_> {
        Box::new(self.items.iter())
    }
    #[inline]
    pub fn iter_mut(&mut self) -> ObjectIterMut<'_> {
        Box::new(
            self.items
                .iter_mut2()
                .map(|(k, v)| (ObjectKeyMut::new(k), v)),
        )
    }
    #[inline]
    pub fn trailing(&self) -> &RawString {
        &self.trailing
    }
    #[inline]
    pub fn set_trailing(&mut self, trailing: impl Into<RawString>) {
        self.trailing = trailing.into();
    }
    pub(crate) fn despan(&mut self, input: &str) {
        self.decor.despan(input);
        self.trailing.despan(input);
        for (key, value) in self.items.iter_mut2() {
            key.despan(input);
            value.despan(input);
        }
    }
}
impl PartialEq for Object {
    fn eq(&self, other: &Self) -> bool {
        self.items == other.items && self.trailing == other.trailing
    }
}
impl From<VecMap<ObjectKey, ObjectValue>> for Object {
    fn from(items: VecMap<ObjectKey, ObjectValue>) -> Self {
        Object {
            items,
            ..Default::default()
        }
    }
}
impl<K, V> Extend<(K, V)> for Object
where
    K: Into<ObjectKey>,
    V: Into<ObjectValue>,
{
    fn extend<I>(&mut self, iterable: I)
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let iter = iterable.into_iter();
        let reserve = if self.is_empty() {
            iter.size_hint().0
        } else {
            (iter.size_hint().0 + 1) / 2
        };
        self.items.reserve(reserve);
        iter.for_each(|(k, v)| {
            self.insert(k, v);
        });
    }
}
impl<K, V> FromIterator<(K, V)> for Object
where
    K: Into<ObjectKey>,
    V: Into<ObjectValue>,
{
    fn from_iter<I>(iterable: I) -> Self
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let iter = iterable.into_iter();
        let lower = iter.size_hint().0;
        let mut object = Object::with_capacity(lower);
        object.extend(iter);
        object
    }
}
impl IntoIterator for Object {
    type Item = (ObjectKey, ObjectValue);
    type IntoIter = ObjectIntoIter;
    fn into_iter(self) -> Self::IntoIter {
        Box::new(self.items.into_iter())
    }
}
impl<'a> IntoIterator for &'a Object {
    type Item = (&'a ObjectKey, &'a ObjectValue);
    type IntoIter = ObjectIter<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}
impl<'a> IntoIterator for &'a mut Object {
    type Item = (ObjectKeyMut<'a>, &'a mut ObjectValue);
    type IntoIter = ObjectIterMut<'a>;
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ObjectKey {
    Ident(Decorated<Ident>),
    Expression(Expression),
}
impl ObjectKey {
    pub fn is_ident(&self) -> bool {
        self.as_ident().is_some()
    }
    pub fn as_ident(&self) -> Option<&Ident> {
        match self {
            ObjectKey::Ident(value) => Some(value.value()),
            ObjectKey::Expression(_) => None,
        }
    }
    pub fn is_expr(&self) -> bool {
        self.as_expr().is_some()
    }
    pub fn as_expr(&self) -> Option<&Expression> {
        match self {
            ObjectKey::Expression(value) => Some(value),
            ObjectKey::Ident(_) => None,
        }
    }
    pub(crate) fn despan(&mut self, input: &str) {
        match self {
            ObjectKey::Ident(ident) => ident.decor_mut().despan(input),
            ObjectKey::Expression(expr) => expr.despan(input),
        }
    }
}
impl From<Decorated<Ident>> for ObjectKey {
    fn from(ident: Decorated<Ident>) -> Self {
        ObjectKey::Ident(ident)
    }
}
impl From<Ident> for ObjectKey {
    fn from(ident: Ident) -> Self {
        ObjectKey::from(Decorated::new(ident))
    }
}
impl From<Expression> for ObjectKey {
    fn from(expr: Expression) -> Self {
        ObjectKey::Expression(expr)
    }
}
#[derive(Debug, Eq, PartialEq)]
pub struct ObjectKeyMut<'k> {
    key: &'k mut ObjectKey,
}
impl<'k> ObjectKeyMut<'k> {
    pub(crate) fn new(key: &'k mut ObjectKey) -> ObjectKeyMut<'k> {
        ObjectKeyMut { key }
    }
    pub fn get(&self) -> &ObjectKey {
        self.key
    }
}
impl<'k> ops::Deref for ObjectKeyMut<'k> {
    type Target = ObjectKey;
    fn deref(&self) -> &Self::Target {
        self.get()
    }
}
impl<'k> Decorate for ObjectKeyMut<'k> {
    fn decor(&self) -> &Decor {
        self.key.decor()
    }
    fn decor_mut(&mut self) -> &mut Decor {
        self.key.decor_mut()
    }
}
impl<'k> Span for ObjectKeyMut<'k> {
    fn span(&self) -> Option<Range<usize>> {
        self.key.span()
    }
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum ObjectValueAssignment {
    Colon,
    #[default]
    Equals,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum ObjectValueTerminator {
    None,
    Newline,
    #[default]
    Comma,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ObjectValue {
    expr: Expression,
    assignment: ObjectValueAssignment,
    terminator: ObjectValueTerminator,
}
impl ObjectValue {
    pub fn new(expr: impl Into<Expression>) -> ObjectValue {
        ObjectValue {
            expr: expr.into(),
            assignment: ObjectValueAssignment::default(),
            terminator: ObjectValueTerminator::default(),
        }
    }
    pub fn expr(&self) -> &Expression {
        &self.expr
    }
    pub fn expr_mut(&mut self) -> &mut Expression {
        &mut self.expr
    }
    pub fn into_expr(self) -> Expression {
        self.expr
    }
    pub fn assignment(&self) -> ObjectValueAssignment {
        self.assignment
    }
    pub fn set_assignment(&mut self, sep: ObjectValueAssignment) {
        self.assignment = sep;
    }
    pub fn terminator(&self) -> ObjectValueTerminator {
        self.terminator
    }
    pub fn set_terminator(&mut self, terminator: ObjectValueTerminator) {
        self.terminator = terminator;
    }
    pub(crate) fn despan(&mut self, input: &str) {
        self.expr.despan(input);
    }
}
impl From<Expression> for ObjectValue {
    fn from(expr: Expression) -> Self {
        ObjectValue::new(expr)
    }
}
decorate_impl!(Object);
span_impl!(Object);
forward_decorate_impl!(ObjectKey => { Ident, Expression });
forward_span_impl!(ObjectKey => { Ident, Expression });
#[cfg(test)]
mod tests {
    use super::*;
    use crate::expr::Array;
    use pretty_assertions::assert_eq;
    #[test]
    fn object_access() {
        let mut obj = Object::new();
        let mut key = ObjectKey::from(Ident::new("foo"));
        key.decorate(("/* prefix */", "/* suffix */"));
        let value = ObjectValue::from(Expression::from("bar"));
        obj.insert(key.clone(), value.clone());
        assert_eq!(obj.get(&key), Some(&value));
        key.decor_mut().clear();
        assert_eq!(obj.get(&key), Some(&value));
        let (key, _) = obj.remove_entry(&key).unwrap();
        assert_eq!(key.decor().prefix(), Some(&RawString::from("/* prefix */")));
        assert_eq!(key.decor().suffix(), Some(&RawString::from("/* suffix */")));
        let mut array = Array::new();
        array.push("foo");
        let mut key = ObjectKey::from(Expression::from(array));
        key.decorate(("/* prefix */", "/* suffix */"));
        let value = ObjectValue::from(Expression::from("bar"));
        obj.insert(key.clone(), value.clone());
        assert_eq!(obj.get(&key), Some(&value));
        key.decor_mut().clear();
        assert_eq!(obj.get(&key), Some(&value));
        let (key, _) = obj.remove_entry(&key).unwrap();
        assert_eq!(key.decor().prefix(), Some(&RawString::from("/* prefix */")));
        assert_eq!(key.decor().suffix(), Some(&RawString::from("/* suffix */")));
    }
}