use std::fmt::Display;

use super::GTag;
use glib::Boxed;
use news_flash::models::Tag;

#[derive(Clone, Debug, Default, Eq, Boxed)]
#[boxed_type(name = "NewsFlashGTags")]
pub struct GTags(Vec<GTag>);

impl PartialEq for GTags {
    fn eq(&self, other: &Self) -> bool {
        if self.len() != other.len() {
            return false;
        }

        self.0
            .iter()
            .enumerate()
            .all(|(i, tag)| other.0.get(i).map(|other| tag.eq(other)).unwrap_or(false))
    }
}

impl From<Vec<Tag>> for GTags {
    fn from(dt: Vec<Tag>) -> Self {
        Self(dt.into_iter().map(GTag::from).collect())
    }
}

impl From<GTags> for Vec<GTag> {
    fn from(dt: GTags) -> Self {
        dt.0
    }
}

impl<'a> From<&'a GTags> for &'a [GTag] {
    fn from(dt: &'a GTags) -> Self {
        &dt.0
    }
}

impl AsRef<[GTag]> for GTags {
    fn as_ref(&self) -> &[GTag] {
        &self.0
    }
}

impl Display for GTags {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let list = self.0.iter().map(GTag::to_string).collect::<Vec<_>>().join(", ");
        write!(f, "{{ {list} }}")
    }
}

impl GTags {
    pub fn len(&self) -> usize {
        self.0.len()
    }

    pub fn push(&mut self, tag: GTag) {
        self.0.push(tag);
    }

    pub fn remove(&mut self, index: usize) {
        self.0.remove(index);
    }
}
