use std::{borrow::Cow, fmt::Display, str::FromStr};

use bstr::{BStr, BString, ByteVec};

use crate::{
    file::Metadata,
    parse,
    parse::{section, Event},
    value::normalize,
    File,
};

impl FromStr for File<'static> {
    type Err = parse::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        parse::Events::from_bytes_owned(s.as_bytes(), None)
            .map(|events| File::from_parse_events_no_includes(events, Metadata::api()))
    }
}

impl<'a> TryFrom<&'a str> for File<'a> {
    type Error = parse::Error;

    /// Convenience constructor. Attempts to parse the provided string into a
    /// [`File`]. See [`Events::from_str()`][crate::parse::Events::from_str()] for more information.
    fn try_from(s: &'a str) -> Result<File<'a>, Self::Error> {
        parse::Events::from_str(s).map(|events| Self::from_parse_events_no_includes(events, Metadata::api()))
    }
}

impl<'a> TryFrom<&'a BStr> for File<'a> {
    type Error = parse::Error;

    /// Convenience constructor. Attempts to parse the provided byte string into
    /// a [`File`]. See [`Events::from_bytes()`][parse::Events::from_bytes()] for more information.
    fn try_from(value: &'a BStr) -> Result<File<'a>, Self::Error> {
        parse::Events::from_bytes(value, None)
            .map(|events| Self::from_parse_events_no_includes(events, Metadata::api()))
    }
}

impl From<File<'_>> for BString {
    fn from(c: File<'_>) -> Self {
        c.into()
    }
}

impl Display for File<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        Display::fmt(&self.to_bstring(), f)
    }
}

impl PartialEq for File<'_> {
    fn eq(&self, other: &Self) -> bool {
        fn find_key<'a>(mut it: impl Iterator<Item = &'a Event<'a>>) -> Option<&'a section::Key<'a>> {
            it.find_map(|e| match e {
                Event::SectionKey(k) => Some(k),
                _ => None,
            })
        }
        fn collect_value<'a>(it: impl Iterator<Item = &'a Event<'a>>) -> Cow<'a, BStr> {
            let mut partial_value = BString::default();
            let mut value = None;

            for event in it {
                match event {
                    Event::SectionKey(_) => break,
                    Event::Value(v) => {
                        value = v.clone().into();
                        break;
                    }
                    Event::ValueNotDone(v) => partial_value.push_str(v.as_ref()),
                    Event::ValueDone(v) => {
                        partial_value.push_str(v.as_ref());
                        value = Some(partial_value.into());
                        break;
                    }
                    _ => (),
                }
            }
            value.map(normalize).unwrap_or_default()
        }
        if self.section_order.len() != other.section_order.len() {
            return false;
        }

        for (lhs, rhs) in self
            .section_order
            .iter()
            .zip(&other.section_order)
            .map(|(lhs, rhs)| (&self.sections[lhs], &other.sections[rhs]))
        {
            if !(lhs.header.name == rhs.header.name && lhs.header.subsection_name == rhs.header.subsection_name) {
                return false;
            }

            let (mut lhs, mut rhs) = (lhs.body.0.iter(), rhs.body.0.iter());
            while let (Some(lhs_key), Some(rhs_key)) = (find_key(&mut lhs), find_key(&mut rhs)) {
                if lhs_key != rhs_key {
                    return false;
                }
                if collect_value(&mut lhs) != collect_value(&mut rhs) {
                    return false;
                }
            }
        }
        true
    }
}
