# Copyright Sunhpc Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import functools
import os
import re
from typing import Optional

import sunhpc.paths

#: PEP440 canonical <major>.<minor>.<micro>.<devN> string
__version__ = "1.0.0.dev0"
sunhpc_version = __version__

#: The current Package API version implemented by this version of Sunhpc. The Package API defines
#: the Python interface for packages as well as the layout of package repositories. The minor
#: version is incremented when the package API is extended in a backwards-compatible way. The major
#: version is incremented upon breaking changes. This version is changed independently from the
#: Sunhpc version.
package_api_version = (2, 4)

#: The minimum Package API version that this version of Sunhpc is compatible with. This should
#: always be a tuple of the form ``(major, 0)``, since compatibility with vX.Y implies
#: compatibility with vX.0.
min_package_api_version = (1, 0)


def __try_int(v):
    try:
        return int(v)
    except ValueError:
        return v


#: (major, minor, micro, dev release) tuple
sunhpc_version_info = tuple([__try_int(v) for v in __version__.split(".")])


@functools.lru_cache(maxsize=None)
def get_sunhpc_commit() -> Optional[str]:
    """Get the Sunhpc git commit sha.

    Returns:
        (str or None) the commit sha if available, otherwise None
    """
    git_path = os.path.join(sunhpc.paths.prefix, ".git")
    if not os.path.exists(git_path):
        return None

    git = sunhpc.util.git.git()
    if not git:
        return None

    rev = git(
        "-C",
        sunhpc.paths.prefix,
        "rev-parse",
        "HEAD",
        output=str,
        error=os.devnull,
        fail_on_error=False,
    )
    if git.returncode != 0:
        return None

    match = re.match(r"[a-f\d]{7,}$", rev)
    return match.group(0) if match else None


def get_version() -> str:
    """Get a descriptive version of this instance of Sunhpc.

    Outputs ``"<PEP440 version> (<git commit sha>)"``.

    The commit sha is only added when available.
    """
    commit = get_sunhpc_commit()
    if commit:
        return f"{sunhpc_version} ({commit})"
    return sunhpc_version


def get_short_version() -> str:
    """Short Sunhpc version."""
    return f"{sunhpc_version_info[0]}.{sunhpc_version_info[1]}"


__all__ = [
    "sunhpc_version_info",
    "sunhpc_version",
    "get_version",
    "get_sunhpc_commit",
    "get_short_version",
    "package_api_version",
    "min_package_api_version",
]
