#![allow(clippy::result_large_err)]
//! Submodule plumbing and abstractions
//!
use std::{
    borrow::Cow,
    cell::{Ref, RefCell, RefMut},
    path::PathBuf,
};

pub use gix_submodule::*;

use crate::{bstr::BStr, worktree::IndexPersistedOrInMemory, Repository, Submodule};

pub(crate) type ModulesFileStorage = gix_features::threading::OwnShared<gix_fs::SharedFileSnapshotMut<File>>;
/// A lazily loaded and auto-updated worktree index.
pub type ModulesSnapshot = gix_fs::SharedFileSnapshot<File>;

/// The name of the file containing (sub) module information.
pub(crate) const MODULES_FILE: &str = ".gitmodules";

mod errors;
pub use errors::*;

/// A platform maintaining state needed to interact with submodules, created by [`Repository::submodules()].
pub(crate) struct SharedState<'repo> {
    pub(crate) repo: &'repo Repository,
    pub(crate) modules: ModulesSnapshot,
    is_active: RefCell<Option<IsActiveState>>,
    index: RefCell<Option<IndexPersistedOrInMemory>>,
}

impl<'repo> SharedState<'repo> {
    pub(crate) fn new(repo: &'repo Repository, modules: ModulesSnapshot) -> Self {
        SharedState {
            repo,
            modules,
            is_active: RefCell::new(None),
            index: RefCell::new(None),
        }
    }

    fn index(&self) -> Result<Ref<'_, IndexPersistedOrInMemory>, crate::repository::index_or_load_from_head::Error> {
        {
            let mut state = self.index.borrow_mut();
            if state.is_none() {
                *state = self.repo.index_or_load_from_head()?.into();
            }
        }
        Ok(Ref::map(self.index.borrow(), |opt| {
            opt.as_ref().expect("just initialized")
        }))
    }

    fn active_state_mut(
        &self,
    ) -> Result<(RefMut<'_, IsActivePlatform>, RefMut<'_, gix_worktree::Stack>), is_active::Error> {
        let mut state = self.is_active.borrow_mut();
        if state.is_none() {
            let platform = self
                .modules
                .is_active_platform(&self.repo.config.resolved, self.repo.config.pathspec_defaults()?)?;
            let index = self.index()?;
            let attributes = self
                .repo
                .attributes_only(
                    &index,
                    gix_worktree::stack::state::attributes::Source::WorktreeThenIdMapping
                        .adjust_for_bare(self.repo.is_bare()),
                )?
                .detach();
            *state = Some(IsActiveState { platform, attributes });
        }
        Ok(RefMut::map_split(state, |opt| {
            let state = opt.as_mut().expect("populated above");
            (&mut state.platform, &mut state.attributes)
        }))
    }
}

struct IsActiveState {
    platform: IsActivePlatform,
    attributes: gix_worktree::Stack,
}

///Access
impl<'repo> Submodule<'repo> {
    /// Return the submodule's name.
    pub fn name(&self) -> &BStr {
        self.name.as_ref()
    }
    /// Return the path at which the submodule can be found, relative to the repository.
    ///
    /// For details, see [gix_submodule::File::path()].
    pub fn path(&self) -> Result<Cow<'_, BStr>, config::path::Error> {
        self.state.modules.path(self.name())
    }

    /// Return the url from which to clone or update the submodule.
    ///
    /// This method takes into consideration submodule configuration overrides.
    pub fn url(&self) -> Result<gix_url::Url, config::url::Error> {
        self.state.modules.url(self.name())
    }

    /// Return the `update` field from this submodule's configuration, if present, or `None`.
    ///
    /// This method takes into consideration submodule configuration overrides.
    pub fn update(&self) -> Result<Option<config::Update>, config::update::Error> {
        self.state.modules.update(self.name())
    }

    /// Return the `branch` field from this submodule's configuration, if present, or `None`.
    ///
    /// This method takes into consideration submodule configuration overrides.
    pub fn branch(&self) -> Result<Option<config::Branch>, config::branch::Error> {
        self.state.modules.branch(self.name())
    }

    /// Return the `fetchRecurseSubmodules` field from this submodule's configuration, or retrieve the value from `fetch.recurseSubmodules` if unset.
    pub fn fetch_recurse(&self) -> Result<Option<config::FetchRecurse>, fetch_recurse::Error> {
        Ok(match self.state.modules.fetch_recurse(self.name())? {
            Some(val) => Some(val),
            None => self
                .state
                .repo
                .config
                .resolved
                .boolean_by_key("fetch.recurseSubmodules")
                .map(|res| crate::config::tree::Fetch::RECURSE_SUBMODULES.try_into_recurse_submodules(res))
                .transpose()?,
        })
    }

    /// Return the `ignore` field from this submodule's configuration, if present, or `None`.
    ///
    /// This method takes into consideration submodule configuration overrides.
    pub fn ignore(&self) -> Result<Option<config::Ignore>, config::Error> {
        self.state.modules.ignore(self.name())
    }

    /// Return the `shallow` field from this submodule's configuration, if present, or `None`.
    ///
    /// If `true`, the submodule will be checked out with `depth = 1`. If unset, `false` is assumed.
    pub fn shallow(&self) -> Result<Option<bool>, gix_config::value::Error> {
        self.state.modules.shallow(self.name())
    }

    /// Returns true if this submodule is considered active and can thus participate in an operation.
    ///
    /// Please see the [plumbing crate documentation](gix_submodule::IsActivePlatform::is_active()) for details.
    pub fn is_active(&self) -> Result<bool, is_active::Error> {
        let (mut platform, mut attributes) = self.state.active_state_mut()?;
        let is_active = platform.is_active(&self.state.repo.config.resolved, self.name.as_ref(), {
            &mut |relative_path, case, is_dir, out| {
                attributes
                    .set_case(case)
                    .at_entry(relative_path, Some(is_dir), &self.state.repo.objects)
                    .map_or(false, |platform| platform.matching_attributes(out))
            }
        })?;
        Ok(is_active)
    }

    /// Return the object id of the submodule as stored in the index of the superproject,
    /// or `None` if it was deleted from the index.
    ///
    /// If `None`, but `Some()` when calling [`Self::head_id()`], then the submodule was just deleted but the change
    /// wasn't yet committed. Note that `None` is also returned if the entry at the submodule path isn't a submodule.
    /// If `Some()`, but `None` when calling [`Self::head_id()`], then the submodule was just added without having committed the change.
    pub fn index_id(&self) -> Result<Option<gix_hash::ObjectId>, index_id::Error> {
        let path = self.path()?;
        Ok(self
            .state
            .index()?
            .entry_by_path(&path)
            .and_then(|entry| (entry.mode == gix_index::entry::Mode::COMMIT).then_some(entry.id)))
    }

    /// Return the object id of the submodule as stored in `HEAD^{tree}` of the superproject, or `None` if it wasn't yet committed.
    ///
    /// If `Some()`, but `None` when calling [`Self::index_id()`], then the submodule was just deleted but the change
    /// wasn't yet committed. Note that `None` is also returned if the entry at the submodule path isn't a submodule.
    /// If `None`, but `Some()` when calling [`Self::index_id()`], then the submodule was just added without having committed the change.
    pub fn head_id(&self) -> Result<Option<gix_hash::ObjectId>, head_id::Error> {
        let path = self.path()?;
        Ok(self
            .state
            .repo
            .head_commit()?
            .tree()?
            .peel_to_entry_by_path(gix_path::from_bstr(path.as_ref()))?
            .and_then(|entry| (entry.mode().is_commit()).then_some(entry.inner.oid)))
    }

    /// Return the path at which the repository of the submodule should be located.
    ///
    /// The directory might not exist yet.
    pub fn git_dir(&self) -> PathBuf {
        self.state
            .repo
            .common_dir()
            .join("modules")
            .join(gix_path::from_bstr(self.name()))
    }

    /// Return the path to the location at which the workdir would be checked out.
    ///
    /// Note that it may be a path relative to the repository if, for some reason, the parent directory
    /// doesn't have a working dir set.
    pub fn work_dir(&self) -> Result<PathBuf, config::path::Error> {
        let worktree_git = gix_path::from_bstr(self.path()?);
        Ok(match self.state.repo.work_dir() {
            None => worktree_git.into_owned(),
            Some(prefix) => prefix.join(worktree_git),
        })
    }

    /// Return the path at which the repository of the submodule should be located, or the path inside of
    /// the superproject's worktree where it actually *is* located if the submodule in the 'old-form', thus is a directory
    /// inside of the superproject's work-tree.
    ///
    /// Note that 'old-form' paths returned aren't verified, i.e. the `.git` repository might be corrupt or otherwise
    /// invalid - it's left to the caller to try to open it.
    ///
    /// Also note that the returned path may not actually exist.
    pub fn git_dir_try_old_form(&self) -> Result<PathBuf, config::path::Error> {
        let worktree_git = self.work_dir()?.join(gix_discover::DOT_GIT_DIR);
        Ok(if worktree_git.is_dir() {
            worktree_git
        } else {
            self.git_dir()
        })
    }

    /// Query various parts of the submodule and assemble it into state information.
    #[doc(alias = "status", alias = "git2")]
    pub fn state(&self) -> Result<State, config::path::Error> {
        let maybe_old_path = self.git_dir_try_old_form()?;
        let git_dir = self.git_dir();
        let worktree_git = self.work_dir()?.join(gix_discover::DOT_GIT_DIR);
        let superproject_configuration = self
            .state
            .repo
            .config
            .resolved
            .sections_by_name("submodule")
            .into_iter()
            .flatten()
            .any(|section| section.header().subsection_name() == Some(self.name.as_ref()));
        Ok(State {
            repository_exists: maybe_old_path.is_dir(),
            is_old_form: maybe_old_path != git_dir,
            worktree_checkout: worktree_git.exists(),
            superproject_configuration,
        })
    }

    /// Open the submodule as repository, or `None` if the submodule wasn't initialized yet.
    ///
    /// More states can be derived here:
    ///
    /// * *initialized* - a repository exists, i.e. `Some(repo)` and the working tree is present.
    /// * *uninitialized* - a repository does not exist, i.e. `None`
    /// * *deinitialized* - a repository does exist, i.e. `Some(repo)`, but its working tree is empty.
    ///
    /// Also see the [state()](Self::state()) method for learning about the submodule.
    /// The repository can also be used to learn about the submodule `HEAD`, i.e. where its working tree is at,
    /// which may differ compared to the superproject's index or `HEAD` commit.
    pub fn open(&self) -> Result<Option<Repository>, open::Error> {
        match crate::open_opts(self.git_dir_try_old_form()?, self.state.repo.options.clone()) {
            Ok(repo) => Ok(Some(repo)),
            Err(crate::open::Error::NotARepository { .. }) => Ok(None),
            Err(err) => Err(err.into()),
        }
    }
}

///
#[allow(clippy::empty_docs)]
#[cfg(feature = "status")]
pub mod status {
    use super::{head_id, index_id, open, Status};
    use crate::Submodule;
    use gix_submodule::config;

    /// The error returned by [Submodule::status()].
    #[derive(Debug, thiserror::Error)]
    #[allow(missing_docs)]
    pub enum Error {
        #[error(transparent)]
        State(#[from] config::path::Error),
        #[error(transparent)]
        HeadId(#[from] head_id::Error),
        #[error(transparent)]
        IndexId(#[from] index_id::Error),
        #[error(transparent)]
        OpenRepository(#[from] open::Error),
        #[error(transparent)]
        IgnoreConfiguration(#[from] config::Error),
        #[error(transparent)]
        StatusPlatform(#[from] crate::status::Error),
        #[error(transparent)]
        Status(#[from] crate::status::index_worktree::iter::Error),
        #[error(transparent)]
        IndexWorktreeStatus(#[from] crate::status::index_worktree::Error),
    }

    impl<'repo> Submodule<'repo> {
        /// Return the status of the submodule.
        ///
        /// Use `ignore` to control the portion of the submodule status to ignore. It can be obtained from
        /// submodule configuration using the [`ignore()`](Submodule::ignore()) method.
        /// If `check_dirty` is `true`, the computation will stop once the first in a ladder operations
        /// ordered from cheap to expensive shows that the submodule is dirty.
        /// Thus, submodules that are clean will still impose the complete set of computation, as given.
        #[doc(alias = "submodule_status", alias = "git2")]
        pub fn status(
            &self,
            ignore: config::Ignore,
            check_dirty: bool,
        ) -> Result<crate::submodule::status::types::Status, Error> {
            self.status_opts(ignore, check_dirty, &mut |s| s)
        }
        /// Return the status of the submodule, just like [`status`](Self::status), but allows to adjust options
        /// for more control over how the status is performed.
        ///
        /// Use `&mut std::convert::identity` for `adjust_options` if no specific options are desired.
        /// A reason to change them might be to enable sorting to enjoy deterministic order of changes.
        ///
        /// The status allows to easily determine if a submodule [has changes](Status::is_dirty).
        ///
        /// ### Incomplete Implementation Warning
        ///
        /// Currently, changes between the head and the index aren't computed.
        // TODO: Run the full status, including tree->index once available.
        #[doc(alias = "submodule_status", alias = "git2")]
        pub fn status_opts(
            &self,
            ignore: config::Ignore,
            check_dirty: bool,
            adjust_options: &mut dyn for<'a> FnMut(
                crate::status::Platform<'a, gix_features::progress::Discard>,
            )
                -> crate::status::Platform<'a, gix_features::progress::Discard>,
        ) -> Result<Status, Error> {
            let mut state = self.state()?;
            if ignore == config::Ignore::All {
                return Ok(Status {
                    state,
                    ..Default::default()
                });
            }

            let index_id = self.index_id()?;
            if !state.repository_exists {
                return Ok(Status {
                    state,
                    index_id,
                    ..Default::default()
                });
            }
            let sm_repo = match self.open()? {
                None => {
                    state.repository_exists = false;
                    return Ok(Status {
                        state,
                        index_id,
                        ..Default::default()
                    });
                }
                Some(repo) => repo,
            };

            let checked_out_head_id = sm_repo.head_id().ok().map(crate::Id::detach);
            let mut status = Status {
                state,
                index_id,
                checked_out_head_id,
                ..Default::default()
            };
            if ignore == config::Ignore::Dirty || check_dirty && status.is_dirty() == Some(true) {
                return Ok(status);
            }

            if !state.worktree_checkout {
                return Ok(status);
            }
            let statusses = adjust_options(sm_repo.status(gix_features::progress::Discard)?)
                .index_worktree_options_mut(|opts| {
                    if ignore == config::Ignore::Untracked {
                        opts.dirwalk_options = None;
                    }
                })
                .into_index_worktree_iter(Vec::new())?;
            let mut changes = Vec::new();
            for change in statusses {
                changes.push(change?);
            }
            status.changes = Some(changes);
            Ok(status)
        }
    }

    impl Status {
        /// Return `Some(true)` if the submodule status could be determined sufficiently and
        /// if there are changes that would render this submodule dirty.
        ///
        /// Return `Some(false)` if the submodule status could be determined and it has no changes
        /// at all.
        ///
        /// Return `None` if the repository clone or the worktree are missing entirely, which would leave
        /// it to the caller to determine if that's considered dirty or not.
        pub fn is_dirty(&self) -> Option<bool> {
            if !self.state.worktree_checkout || !self.state.repository_exists {
                return None;
            }
            let is_dirty =
                self.checked_out_head_id != self.index_id || self.changes.as_ref().map_or(false, |c| !c.is_empty());
            Some(is_dirty)
        }
    }

    pub(super) mod types {
        use crate::submodule::State;

        /// A simplified status of the Submodule.
        ///
        /// As opposed to the similar-sounding [`State`], it is more exhaustive and potentially expensive to compute,
        /// particularly for submodules without changes.
        ///
        /// It's produced by [Submodule::status()](crate::Submodule::status()).
        #[derive(Default, Clone, PartialEq, Debug)]
        pub struct Status {
            /// The cheapest part of the status that is always performed, to learn if the repository is cloned
            /// and if there is a worktree checkout.
            pub state: State,
            /// The commit at which the submodule is supposed to be according to the super-project's index.
            /// `None` means the computation wasn't performed, or the submodule didn't exist in the super-project's index anymore.
            pub index_id: Option<gix_hash::ObjectId>,
            /// The commit-id of the `HEAD` at which the submodule is currently checked out.
            /// `None` if the computation wasn't performed as it was skipped early, or if no repository was available or
            /// if the HEAD could not be obtained or wasn't born.
            pub checked_out_head_id: Option<gix_hash::ObjectId>,
            /// The set of changes obtained from running something akin to `git status` in the submodule working tree.
            ///
            /// `None` if the computation wasn't performed as the computation was skipped early, or if no working tree was
            /// available or repository was available.
            pub changes: Option<Vec<crate::status::index_worktree::iter::Item>>,
        }
    }
}
#[cfg(feature = "status")]
pub use status::types::Status;

/// A summary of the state of all parts forming a submodule, which allows to answer various questions about it.
///
/// Note that expensive questions about its presence in the `HEAD` or the `index` are left to the caller.
#[derive(Default, Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct State {
    /// if the submodule repository has been cloned.
    pub repository_exists: bool,
    /// if the submodule repository is located directly in the worktree of the superproject.
    pub is_old_form: bool,
    /// if the worktree is checked out.
    pub worktree_checkout: bool,
    /// If submodule configuration was found in the superproject's `.git/config` file.
    /// Note that the presence of a single section is enough, independently of the actual values.
    pub superproject_configuration: bool,
}
