import os.path as path
import subprocess
import shlex
from sphinx.util import logging
from docutils import nodes
logger = logging.getLogger(__name__)


# use an old git trick, to get the top-level, could have used ../ etc.. but
# this will be fine..
top = subprocess.check_output(shlex.split(
    "git rev-parse --show-toplevel")).strip().decode("utf-8")


def make_ref(text):
    """ Make hyperlink to Github """
    full_path = path.join(top, text)
    if path.isfile(full_path):
        ref = "https://www.github.com/numba/numba/blob/main/" + text
    elif path.isdir(full_path):
        ref = "https://www.github.com/numba/numba/tree/main/" + text
    else:
        logger.warn("Failed to find file in repomap: " + text)
        ref = "https://www.github.com/numba/numba"
    return ref


def intersperse(lst, item):
    """ Insert item between each item in lst.

    Copied under CC-BY-SA from stackoverflow at:

    https://stackoverflow.com/questions/5920643/
    add-an-item-between-each-item-already-in-the-list

    """
    result = [item] * (len(lst) * 2 - 1)
    result[0::2] = lst
    return result


def ghfile_role(name, rawtext, text, lineno, inliner, options=None, content=None):
    """ Emit hyperlink nodes for a given file in repomap. """
    if options is None:
        options = {}
    if content is None:
        content = []
    my_nodes = []
    if "{" in text:  # myfile.{c,h} - make two nodes
        # could have used regexes, but this will be fine..
        base = text[:text.find(".") + 1]
        exts = text[text.find("{") + 1:text.find("}")].split(",")
        for e in exts:
            node = nodes.reference(rawtext,
                                   base + e,
                                   refuri=make_ref(base + e),
                                   **options)
            my_nodes.append(node)
    elif "*" in text:  # path/*_files.py - link to directory
        # Could have used something from os.path, but this will be fine..
        ref = path.dirname(text) + path.sep
        node = nodes.reference(rawtext, text, refuri=make_ref(ref), **options)
        my_nodes.append(node)
    else:  # everything else is taken verbatim
        node = nodes.reference(rawtext, text, refuri=make_ref(text), **options)
        my_nodes.append(node)

    # insert separators if needed
    if len(my_nodes) > 1:
        my_nodes = intersperse(my_nodes, nodes.Text(" | "))
    return my_nodes, []


def setup(app):
    logger.info('Initializing ghfiles plugin')
    app.add_role('ghfile', ghfile_role)

    metadata = {'parallel_read_safe': True, 'parallel_write_safe': True}
    return metadata
