from pathlib import Path
from json import loads
import re

from hotdoc.core.exceptions import HotdocSourceException
from hotdoc.core.extension import Extension
from hotdoc.core.tree import Page
from hotdoc.core.project import Project
from hotdoc.run_hotdoc import Application
from hotdoc.core.formatter import Formatter
from hotdoc.utils.loggable import Logger, warn, info

import typing as T

if T.TYPE_CHECKING:
    import argparse

Logger.register_warning_code('unknown-refman-link', HotdocSourceException, 'refman-links')

class RefmanLinksExtension(Extension):
    extension_name = 'refman-links'
    argument_prefix = 'refman'

    def __init__(self, app: Application, project: Project):
        self.project: Project
        super().__init__(app, project)
        self._data_file: T.Optional[Path] = None
        self._data: T.Dict[str, str] = {}

    @staticmethod
    def add_arguments(parser: 'argparse.ArgumentParser'):
        group = parser.add_argument_group(
            'Refman links',
            'Custom Meson extension',
        )

        # Add Arguments with `group.add_argument(...)`
        group.add_argument(
            f'--refman-data-file',
            help="JSON file with the mappings to replace",
            default=None,
        )

    def parse_config(self, config: T.Dict[str, T.Any]) -> None:
        super().parse_config(config)
        self._data_file = config.get('refman_data_file')

    def _formatting_page_cb(self, formatter: Formatter, page: Page) -> None:
        ''' Replace Meson refman tags

        Links of the form [[function]] are automatically replaced
        with valid links to the correct URL. To reference objects / types use the
        [[@object]] syntax.
        '''
        link_regex = re.compile(r'(\[\[#?@?([ \n\t]*[a-zA-Z0-9_]+[ \n\t]*\.)*[ \n\t]*[a-zA-Z0-9_]+[ \n\t]*\]\])(.)?', re.MULTILINE)
        for m in link_regex.finditer(page.formatted_contents):
            i = m.group(1)
            obj_id: str = i[2:-2]
            obj_id = re.sub(r'[ \n\t]', '', obj_id)  # Remove whitespaces

            # Marked as inside a code block?
            in_code_block = False
            if obj_id.startswith('#'):
                in_code_block = True
                obj_id = obj_id[1:]

            if obj_id not in self._data:
                warn('unknown-refman-link', f'{Path(page.name).name}: Unknown Meson refman link: "{obj_id}"')
                continue

            # Just replaces [[!file.id]] paths with the page file (no fancy HTML)
            if obj_id.startswith('!'):
                page.formatted_contents = page.formatted_contents.replace(i, self._data[obj_id])
                continue

            # Fancy links for functions and methods
            text = obj_id
            if text.startswith('@'):
                text = text[1:]
            elif in_code_block:
                if m.group(3) != '(':
                    text = text + '()'
            else:
                text = text + '()'
            if not in_code_block:
                text = f'<code>{text}</code>'
            link = f'<a href="{self._data[obj_id]}"><ins>{text}</ins></a>'
            page.formatted_contents = page.formatted_contents.replace(i, link, 1)

    def setup(self) -> None:
        super().setup()

        if not self._data_file:
            info('Meson refman extension DISABLED')
            return

        raw = Path(self._data_file).read_text(encoding='utf-8')
        self._data = loads(raw)

        # Register formatter
        for ext in self.project.extensions.values():
            ext = T.cast(Extension, ext)
            ext.formatter.formatting_page_signal.connect(self._formatting_page_cb)
        info('Meson refman extension LOADED')

    @staticmethod
    def get_dependencies() -> T.List[T.Type[Extension]]:
        return []  # In case this extension has dependencies on other extensions

def get_extension_classes() -> T.List[T.Type[Extension]]:
    return [RefmanLinksExtension]
