# SPDX-FileCopyrightText: © 2023 Christian BUHTZ <c.buhtz@posteo.jp>
#
# SPDX-License-Identifier: GPL-3.0-only
#
# This file is part of the program "Hyperorg" which is released under GNU
# General Public License v3 (GPLv3).
# See folder LICENSES or go to <https://www.gnu.org/licenses/#GPL>.
"""The Hyperorg package.

See README.md and LICENSE for further details.
"""
import pathlib
import os
import re
from collections import Counter
from importlib.metadata import metadata


def _package_metadata_as_dict(exclude_keys: list = ('Classifier'),
                              license_lines: int = 2,
                              ) -> dict:
    """Get package metadata and return it as a dict."""

    m = metadata(__name__)

    result = {}

    for key, count in Counter(m.keys()).items():

        if key in exclude_keys:
            continue

        # single value key
        if count == 1:
            result[key] = m[key]
            continue

        # multi value key
        result[key] = []
        for val in m.get_all(key):
            result[key].append(val)

    # postprocess project URLs
    urls = result['Project-URL']
    result['Project-URL'] = {}
    for entry in urls:
        key, val = entry.split(',')
        result['Project-URL'][key.strip()] = val.strip()

    # post process license data
    result['License'] = result['License'].split('\n')[:license_lines]

    return result


meta = _package_metadata_as_dict()
__version__ = meta['Version']


def get_full_application_string(name_as_url: bool = False) -> str:
    """Build a string representing the application name and its version.

    If a git repo is present information about its current state are
    added also.
    """

    if name_as_url:
        url = meta['Project-URL']['homepage']
        name = f'<a href="{url}">{__name__}</a>'
    else:
        name = __name__

    return f'{name} {__version__}{get_git_string()}'


def get_git_string() -> str:
    """Build a string containing the applications git related
    information."""

    try:
        git = get_git_repository_info()
        return f'(branch: {git["branch"]} at {git["hash"]})'
    except FileNotFoundError:
        return ''


def get_git_repository_info(hash_length: int = 8) -> dict:
    """Return the current branch and last commit hash.

    A special case is when that script runs on a Read The Docs instance. In
    that case the branch name is extracted from environment variables.

    Credits: https://stackoverflow.com/a/51224861/4865723
    """

    git_folder = pathlib.Path.cwd() / '.git'
    result = {}

    # If run on a Read The Docs instance
    if 'READTHEDOCS' in os.environ:
        if os.environ['READTHEDOCS_VERSION_TYPE'] == 'branch':
            result['branch'] = os.environ['READTHEDOCS_VERSION']
    else:
        # branch name
        with (git_folder / 'HEAD').open('r') as handle:
            result['branch'] = '/'.join(handle.read().split('/')[2:]).strip()

    # commit hash
    with (git_folder / 'refs' / 'heads' / result['branch']) \
         .open('r') as handle:
        result['hash'] = handle.read().strip()

    if hash_length is not None:
        result['hash'] = result['hash'][:hash_length]

    return result


_RE_SIMPLIFY_STRING = re.compile(r'[^\w-]')
"""Used in `simplify_string()`."""


def simplify_string(string: str) -> str:
    """Simplify the string.

    While word characters and `-` are kept the rest is replaced by underscore
    `_`. This can be used for filenames.

    Args:
        string: The string to simplify.

    Returns:
        The simplified string.
    """

    return _RE_SIMPLIFY_STRING.sub('_', string)
