use bstr::{BString, ByteSlice};
use gix_glob::Pattern;
use kstring::{KString, KStringRef};

use crate::{
    search::{
        refmap::RefMapKey, Assignments, AttributeId, Attributes, MatchKind, Metadata, MetadataCollection, Outcome,
        TrackedAssignment, Value,
    },
    AssignmentRef, NameRef, StateRef,
};

/// Initialization
impl Outcome {
    /// Initialize this instance to collect outcomes for all names in `collection`, which represents all possible attributes
    /// or macros we may visit, and [`reset`][Self::reset()] it unconditionally.
    ///
    /// This must be called after each time `collection` changes.
    pub fn initialize(&mut self, collection: &MetadataCollection) {
        if self.matches_by_id.len() != collection.name_to_meta.len() {
            let global_num_attrs = collection.name_to_meta.len();

            self.matches_by_id.resize(global_num_attrs, Default::default());

            // NOTE: This works only under the assumption that macros remain defined.
            for (order, macro_attributes) in collection.iter().filter_map(|(_, meta)| {
                (!meta.macro_attributes.is_empty()).then_some((meta.id.0, &meta.macro_attributes))
            }) {
                self.matches_by_id[order].macro_attributes.clone_from(macro_attributes)
            }

            for (name, id) in self.selected.iter_mut().filter(|(_, id)| id.is_none()) {
                *id = collection.name_to_meta.get(name.as_str()).map(|meta| meta.id)
            }
        }
        self.reset();
    }

    /// Like [`initialize()`][Self::initialize()], but limits the set of attributes to look for and fill in
    /// to `attribute_names`.
    /// Users of this instance should prefer to limit their search as this would allow it to finish earlier.
    ///
    /// Note that `attribute_names` aren't validated to be valid names here, as invalid names definitely will always be unspecified.
    pub fn initialize_with_selection<'a>(
        &mut self,
        collection: &MetadataCollection,
        attribute_names: impl IntoIterator<Item = impl Into<KStringRef<'a>>>,
    ) {
        self.initialize_with_selection_inner(collection, &mut attribute_names.into_iter().map(Into::into))
    }

    fn initialize_with_selection_inner(
        &mut self,
        collection: &MetadataCollection,
        attribute_names: &mut dyn Iterator<Item = KStringRef<'_>>,
    ) {
        self.selected.clear();
        self.selected.extend(attribute_names.map(|name| {
            (
                name.to_owned(),
                collection.name_to_meta.get(name.as_str()).map(|meta| meta.id),
            )
        }));

        self.initialize(collection);
        self.reset_remaining();
    }

    /// Prepare for a new search over the known set of attributes by resetting our state.
    pub fn reset(&mut self) {
        self.matches_by_id.iter_mut().for_each(|item| item.r#match = None);
        self.attrs_stack.clear();
        self.reset_remaining();
    }

    fn reset_remaining(&mut self) {
        self.remaining = Some(if self.selected.is_empty() {
            self.matches_by_id.len()
        } else {
            self.selected.iter().filter(|(_name, id)| id.is_some()).count()
        });
    }

    /// A performance optimization which allows results from this instance to be efficiently copied over to `dest`.
    /// For this to work, `collection` must be the one used to initialize our state, and `dest` should not have been initialized
    /// with any meaningful collection initially, i.e. be empty the first time this method is called.
    ///
    /// Note that it's safe to call it multiple times, so that it can be called after this instance was used to store a search result.
    pub fn copy_into(&self, collection: &MetadataCollection, dest: &mut Self) {
        dest.initialize(collection);
        dest.matches_by_id.clone_from(&self.matches_by_id);
        if dest.patterns.len() != self.patterns.len() {
            dest.patterns = self.patterns.clone();
        }
        if dest.assignments.len() != self.assignments.len() {
            dest.assignments = self.assignments.clone();
        }
        if dest.source_paths.len() != self.source_paths.len() {
            dest.source_paths = self.source_paths.clone();
        }
        dest.remaining = self.remaining;
    }
}

/// Access
impl Outcome {
    /// Return an iterator over all filled attributes we were initialized with.
    ///
    /// ### Note
    ///
    /// If [`initialize_with_selection`][Self::initialize_with_selection()] was used,
    /// use [`iter_selected()`][Self::iter_selected()] instead.
    ///
    /// ### Deviation
    ///
    /// It's possible that the order in which the attribute are returned (if not limited to a set of attributes) isn't exactly
    /// the same as what `git` provides.
    /// Ours is in order of declaration, whereas `git` seems to list macros first somehow. Since the values are the same, this
    /// shouldn't be an issue.
    pub fn iter(&self) -> impl Iterator<Item = crate::search::Match<'_>> {
        self.matches_by_id
            .iter()
            .filter_map(|item| item.r#match.as_ref().map(|m| m.to_outer(self)))
    }

    /// Iterate over all matches of the attribute selection in their original order.
    ///
    /// This only yields values if this instance was initialized with [`Outcome::initialize_with_selection()`].
    pub fn iter_selected(&self) -> impl Iterator<Item = crate::search::Match<'_>> {
        static DUMMY: Pattern = Pattern {
            text: BString::new(Vec::new()),
            mode: gix_glob::pattern::Mode::empty(),
            first_wildcard_pos: None,
        };
        self.selected.iter().map(|(name, id)| {
            id.and_then(|id| self.matches_by_id[id.0].r#match.as_ref().map(|m| m.to_outer(self)))
                .unwrap_or_else(|| crate::search::Match {
                    pattern: &DUMMY,
                    assignment: AssignmentRef {
                        name: NameRef::try_from(name.as_bytes().as_bstr())
                            .unwrap_or_else(|_| NameRef("invalid".into())),
                        state: StateRef::Unspecified,
                    },
                    kind: MatchKind::Attribute { macro_id: None },
                    location: crate::search::MatchLocation {
                        source: None,
                        sequence_number: 0,
                    },
                })
        })
    }

    /// Obtain a match by the order of its attribute, if the order exists in our initialized attribute list and there was a match.
    pub fn match_by_id(&self, id: AttributeId) -> Option<crate::search::Match<'_>> {
        self.matches_by_id
            .get(id.0)
            .and_then(|m| m.r#match.as_ref().map(|m| m.to_outer(self)))
    }

    /// Return `true` if there is nothing more to be done as all attributes were filled.
    pub fn is_done(&self) -> bool {
        self.remaining() == 0
    }
}

/// Mutation
impl Outcome {
    /// Fill all `attrs` and resolve them recursively if they are macros. Return `true` if there is no attribute left to be resolved and
    /// we are totally done.
    /// `pattern` is what matched a patch and is passed for contextual information,
    /// providing `sequence_number` and `source` as well.
    pub(crate) fn fill_attributes<'a>(
        &mut self,
        attrs: impl Iterator<Item = &'a TrackedAssignment>,
        pattern: &gix_glob::Pattern,
        source: Option<&std::path::PathBuf>,
        sequence_number: usize,
    ) -> bool {
        self.attrs_stack.extend(
            attrs
                .filter(|attr| self.matches_by_id[attr.id.0].r#match.is_none())
                .map(|attr| (attr.id, attr.inner.clone(), None)),
        );
        while let Some((id, assignment, parent_order)) = self.attrs_stack.pop() {
            let slot = &mut self.matches_by_id[id.0];
            if slot.r#match.is_some() {
                continue;
            }
            // Let's be explicit - this is only non-empty for macros.
            let is_macro = !slot.macro_attributes.is_empty();

            slot.r#match = Some(Match {
                pattern: self.patterns.insert(pattern),
                assignment: self.assignments.insert_owned(assignment),
                kind: if is_macro {
                    MatchKind::Macro {
                        parent_macro_id: parent_order,
                    }
                } else {
                    MatchKind::Attribute { macro_id: parent_order }
                },
                location: MatchLocation {
                    source: source.map(|path| self.source_paths.insert(path)),
                    sequence_number,
                },
            });
            if self.reduce_and_check_if_done(id) {
                return true;
            }

            if is_macro {
                // TODO(borrowchk): one fine day we should be able to re-borrow `slot` without having to redo the array access.
                let slot = &self.matches_by_id[id.0];
                self.attrs_stack.extend(
                    slot.macro_attributes
                        .iter()
                        .filter(|attr| self.matches_by_id[attr.id.0].r#match.is_none())
                        .map(|attr| (attr.id, attr.inner.clone(), Some(id))),
                );
            }
        }
        false
    }
}

impl Outcome {
    /// Given a list of `attrs` by order, return true if at least one of them is not set
    pub(crate) fn has_unspecified_attributes(&self, mut attrs: impl Iterator<Item = AttributeId>) -> bool {
        attrs.any(|order| self.matches_by_id[order.0].r#match.is_none())
    }
    /// Return the amount of attributes haven't yet been found.
    ///
    /// If this number reaches 0, then the search can be stopped as there is nothing more to fill in.
    pub(crate) fn remaining(&self) -> usize {
        self.remaining
            .expect("BUG: instance must be initialized for each search set")
    }

    fn reduce_and_check_if_done(&mut self, attr: AttributeId) -> bool {
        if self.selected.is_empty()
            || self
                .selected
                .iter()
                .any(|(_name, id)| id.map_or(false, |id| id == attr))
        {
            *self.remaining.as_mut().expect("initialized") -= 1;
        }
        self.is_done()
    }
}

impl std::fmt::Debug for Outcome {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        struct AsDisplay<'a>(&'a dyn std::fmt::Display);
        impl std::fmt::Debug for AsDisplay<'_> {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                self.0.fmt(f)
            }
        }

        let mut dbg = f.debug_tuple("Outcome");
        if self.selected.is_empty() {
            for match_ in self.iter() {
                dbg.field(&AsDisplay(&match_.assignment));
            }
        } else {
            for match_ in self.iter_selected() {
                dbg.field(&AsDisplay(&match_.assignment));
            }
        }
        dbg.finish()
    }
}

/// Mutation
impl MetadataCollection {
    /// Assign order ids to each attribute either in macros (along with macros themselves) or attributes of patterns, and store
    /// them in this collection.
    ///
    /// Must be called before querying matches.
    pub fn update_from_list(&mut self, list: &mut gix_glob::search::pattern::List<Attributes>) {
        for pattern in &mut list.patterns {
            match &mut pattern.value {
                Value::MacroAssignments { id: order, assignments } => {
                    *order = self.id_for_macro(
                        pattern
                            .pattern
                            .text
                            .to_str()
                            .expect("valid macro names are always UTF8 and this was verified"),
                        assignments,
                    );
                }
                Value::Assignments(assignments) => {
                    self.assign_order_to_attributes(assignments);
                }
            }
        }
    }
}

/// Access
impl MetadataCollection {
    /// Return an iterator over the contents of the map in an easy-to-consume form.
    pub fn iter(&self) -> impl Iterator<Item = (&str, &Metadata)> {
        self.name_to_meta.iter().map(|(k, v)| (k.as_str(), v))
    }
}

impl MetadataCollection {
    pub(crate) fn id_for_macro(&mut self, name: &str, attrs: &mut Assignments) -> AttributeId {
        let order = match self.name_to_meta.get_mut(name) {
            Some(meta) => meta.id,
            None => {
                let order = AttributeId(self.name_to_meta.len());
                self.name_to_meta.insert(
                    KString::from_ref(name),
                    Metadata {
                        id: order,
                        macro_attributes: Default::default(),
                    },
                );
                order
            }
        };

        self.assign_order_to_attributes(attrs);
        self.name_to_meta
            .get_mut(name)
            .expect("just added")
            .macro_attributes
            .clone_from(attrs);

        order
    }
    pub(crate) fn id_for_attribute(&mut self, name: &str) -> AttributeId {
        match self.name_to_meta.get(name) {
            Some(meta) => meta.id,
            None => {
                let order = AttributeId(self.name_to_meta.len());
                self.name_to_meta.insert(KString::from_ref(name), order.into());
                order
            }
        }
    }
    pub(crate) fn assign_order_to_attributes(&mut self, attributes: &mut [TrackedAssignment]) {
        for TrackedAssignment {
            id: order,
            inner: crate::Assignment { name, .. },
        } in attributes
        {
            *order = self.id_for_attribute(&name.0);
        }
    }
}

impl From<AttributeId> for Metadata {
    fn from(order: AttributeId) -> Self {
        Metadata {
            id: order,
            macro_attributes: Default::default(),
        }
    }
}

impl MatchKind {
    /// return the id of the macro that resolved us, or `None` if that didn't happen.
    pub fn source_id(&self) -> Option<AttributeId> {
        match self {
            MatchKind::Attribute { macro_id: id } | MatchKind::Macro { parent_macro_id: id } => *id,
        }
    }
}

/// A version of `Match` without references.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct Match {
    /// The glob pattern itself, like `/target/*`.
    pub pattern: RefMapKey,
    /// The key=value pair of the attribute that matched at the pattern. There can be multiple matches per pattern.
    pub assignment: RefMapKey,
    /// Additional information about the kind of match.
    pub kind: MatchKind,
    /// Information about the location of the match.
    pub location: MatchLocation,
}

impl Match {
    fn to_outer<'a>(&self, out: &'a Outcome) -> crate::search::Match<'a> {
        crate::search::Match {
            pattern: out.patterns.resolve(self.pattern).expect("pattern still present"),
            assignment: out
                .assignments
                .resolve(self.assignment)
                .expect("assignment present")
                .as_ref(),
            kind: self.kind,
            location: self.location.to_outer(out),
        }
    }
}

/// A version of `MatchLocation` without references.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct MatchLocation {
    /// The path to the source from which the pattern was loaded, or `None` if it was specified by other means.
    pub source: Option<RefMapKey>,
    /// The line at which the pattern was found in its `source` file, or the occurrence in which it was provided.
    pub sequence_number: usize,
}

impl MatchLocation {
    fn to_outer<'a>(&self, out: &'a Outcome) -> crate::search::MatchLocation<'a> {
        crate::search::MatchLocation {
            source: self
                .source
                .and_then(|source| out.source_paths.resolve(source).map(AsRef::as_ref)),
            sequence_number: self.sequence_number,
        }
    }
}
