use std::path::PathBuf;

/// A repository path which either points to a work tree or the `.git` repository itself.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Path {
    /// The currently checked out linked worktree along with its connected and existing git directory, or the worktree checkout of a
    /// submodule.
    LinkedWorkTree {
        /// The base of the work tree.
        work_dir: PathBuf,
        /// The worktree-private git dir, located within the main git directory which holds most of the information.
        git_dir: PathBuf,
    },
    /// The currently checked out or nascent work tree of a git repository
    WorkTree(PathBuf),
    /// The git repository itself, typically bare and without known worktree.
    ///
    /// Note that it might still have linked work-trees which can be accessed later, weather bare or not, or it might be a
    /// submodule git directory in the `.git/modules/**/<name>` directory of the parent repository.
    Repository(PathBuf),
}

mod path {
    use std::path::PathBuf;

    use crate::{
        path::without_dot_git_dir,
        repository::{Kind, Path},
        DOT_GIT_DIR,
    };

    impl AsRef<std::path::Path> for Path {
        fn as_ref(&self) -> &std::path::Path {
            match self {
                Path::WorkTree(path)
                | Path::Repository(path)
                | Path::LinkedWorkTree {
                    work_dir: _,
                    git_dir: path,
                } => path,
            }
        }
    }

    impl Path {
        /// Instantiate a new path from `dir` which is expected to be the `.git` directory, with `kind` indicating
        /// whether it's a bare repository or not, with `current_dir` being used to normalize relative paths
        /// as needed.
        ///
        /// `None` is returned if `dir` could not be resolved due to being relative and trying to reach outside of the filesystem root.
        pub fn from_dot_git_dir(dir: PathBuf, kind: Kind, current_dir: &std::path::Path) -> Option<Self> {
            let cwd = current_dir;
            let normalize_on_trailing_dot_dot = |dir: PathBuf| -> Option<PathBuf> {
                if !matches!(dir.components().next_back(), Some(std::path::Component::ParentDir)) {
                    dir
                } else {
                    gix_path::normalize(dir.into(), cwd)?.into_owned()
                }
                .into()
            };

            match kind {
                Kind::Submodule { git_dir } => Path::LinkedWorkTree {
                    git_dir: gix_path::normalize(git_dir.into(), cwd)?.into_owned(),
                    work_dir: without_dot_git_dir(normalize_on_trailing_dot_dot(dir)?),
                },
                Kind::SubmoduleGitDir => Path::Repository(dir),
                Kind::WorkTreeGitDir { work_dir } => Path::LinkedWorkTree { git_dir: dir, work_dir },
                Kind::WorkTree { linked_git_dir } => match linked_git_dir {
                    Some(git_dir) => Path::LinkedWorkTree {
                        git_dir,
                        work_dir: without_dot_git_dir(normalize_on_trailing_dot_dot(dir)?),
                    },
                    None => {
                        let mut dir = normalize_on_trailing_dot_dot(dir)?;
                        dir.pop(); // ".git" suffix
                        let work_dir = dir.as_os_str().is_empty().then(|| PathBuf::from(".")).unwrap_or(dir);
                        Path::WorkTree(work_dir)
                    }
                },
                Kind::PossiblyBare => Path::Repository(dir),
            }
            .into()
        }
        /// Returns the [kind][Kind] of this repository path.
        pub fn kind(&self) -> Kind {
            match self {
                Path::LinkedWorkTree { work_dir: _, git_dir } => Kind::WorkTree {
                    linked_git_dir: Some(git_dir.to_owned()),
                },
                Path::WorkTree(_) => Kind::WorkTree { linked_git_dir: None },
                Path::Repository(_) => Kind::PossiblyBare,
            }
        }

        /// Consume and split this path into the location of the `.git` directory as well as an optional path to the work tree.
        pub fn into_repository_and_work_tree_directories(self) -> (PathBuf, Option<PathBuf>) {
            match self {
                Path::LinkedWorkTree { work_dir, git_dir } => (git_dir, Some(work_dir)),
                Path::WorkTree(working_tree) => (working_tree.join(DOT_GIT_DIR), Some(working_tree)),
                Path::Repository(repository) => (repository, None),
            }
        }
    }
}

/// The kind of repository path.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Kind {
    /// A bare repository does not have a work tree, that is files on disk beyond the `git` repository itself.
    ///
    /// Note that this is merely a guess at this point as we didn't read the configuration yet.
    ///
    /// Also note that due to optimizing for performance and *just* making an educated *guess in some situations*,
    /// we may consider a non-bare repository bare if it it doesn't have an index yet due to be freshly initialized.
    /// The caller is has to handle this, typically by reading the configuration.
    PossiblyBare,
    /// A `git` repository along with checked out files in a work tree.
    WorkTree {
        /// If set, this is the git dir associated with this _linked_ worktree.
        /// If `None`, the git_dir is the `.git` directory inside the _main_ worktree we represent.
        linked_git_dir: Option<PathBuf>,
    },
    /// A worktree's git directory in the common`.git` directory in `worktrees/<name>`.
    WorkTreeGitDir {
        /// Path to the worktree directory.
        work_dir: PathBuf,
    },
    /// The directory is a `.git` dir file of a submodule worktree.
    Submodule {
        /// The git repository itself that is referenced by the `.git` dir file, typically in the `.git/modules/**/<name>` directory of the parent
        /// repository.
        git_dir: PathBuf,
    },
    /// The git directory in the `.git/modules/**/<name>` directory tree of the parent repository
    SubmoduleGitDir,
}

impl Kind {
    /// Returns true if this is a bare repository, one without a work tree.
    pub fn is_bare(&self) -> bool {
        matches!(self, Kind::PossiblyBare)
    }
}
