# SPDX-License-Identifier: Apache-2.0
# Copyright 2016-2021 The Meson development team

import re
import unittest
from itertools import chain
from pathlib import Path
from unittest import mock

import mesonbuild.mlog
import mesonbuild.depfile
import mesonbuild.dependencies.base
import mesonbuild.dependencies.factory
import mesonbuild.envconfig
import mesonbuild.environment
import mesonbuild.coredata
import mesonbuild.options
import mesonbuild.modules.gnome
from mesonbuild.interpreter import Interpreter
from mesonbuild.ast import AstInterpreter
from mesonbuild.mesonlib import MachineChoice
from mesonbuild.options import OptionKey
from mesonbuild.compilers import (
    detect_c_compiler, detect_cpp_compiler
)
import mesonbuild.modules.pkgconfig


from run_tests import (
    FakeBuild, get_fake_env
)

from .helpers import *

@unittest.skipIf(is_tarball(), 'Skipping because this is a tarball release')
class DataTests(unittest.TestCase):

    def test_snippets(self):
        hashcounter = re.compile('^ *(#)+')
        snippet_dir = Path('docs/markdown/snippets')
        self.assertTrue(snippet_dir.is_dir())
        for f in snippet_dir.glob('*'):
            self.assertTrue(f.is_file())
            if f.parts[-1].endswith('~'):
                continue
            if f.suffix == '.md':
                in_code_block = False
                with f.open(encoding='utf-8') as snippet:
                    for line in snippet:
                        if line.startswith('    '):
                            continue
                        if line.startswith('```'):
                            in_code_block = not in_code_block
                        if in_code_block:
                            continue
                        m = re.match(hashcounter, line)
                        if m:
                            self.assertEqual(len(m.group(0)), 2, 'All headings in snippets must have two hash symbols: ' + f.name)
                self.assertFalse(in_code_block, 'Unclosed code block.')
            else:
                if f.name != 'add_release_note_snippets_here':
                    self.assertTrue(False, 'A file without .md suffix in snippets dir: ' + f.name)

    def test_compiler_options_documented(self):
        '''
        Test that C and C++ compiler options and base options are documented in
        Builtin-Options.md. Only tests the default compiler for the current
        platform on the CI.
        '''
        md = None
        with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
            md = f.read()
        self.assertIsNotNone(md)
        env = get_fake_env()
        # FIXME: Support other compilers
        cc = detect_c_compiler(env, MachineChoice.HOST)
        cpp = detect_cpp_compiler(env, MachineChoice.HOST)
        for comp in (cc, cpp):
            for opt in comp.get_options():
                self.assertIn(str(opt), md)
            for opt in comp.base_options:
                self.assertIn(str(opt), md)
        self.assertNotIn('b_unknown', md)

    @staticmethod
    def _get_section_content(name, sections, md):
        for section in sections:
            if section and section.group(1) == name:
                try:
                    next_section = next(sections)
                    end = next_section.start()
                except StopIteration:
                    end = len(md)
                # Extract the content for this section
                return md[section.end():end]
        raise RuntimeError(f'Could not find "{name}" heading')

    def test_builtin_options_documented(self):
        '''
        Test that universal options and base options are documented in
        Builtin-Options.md.
        '''
        from itertools import tee
        md = None
        with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
            md = f.read()
        self.assertIsNotNone(md)

        found_entries = set()
        sections = re.finditer(r"^## (.+)$", md, re.MULTILINE)
        # Extract the content for this section
        u_subcontents = []
        content = self._get_section_content("Universal options", sections, md)
        subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE))
        u_subcontents.append(self._get_section_content("Directories", subsections[0], content))
        u_subcontents.append(self._get_section_content("Core options", subsections[1], content))

        mod_subcontents = []
        content = self._get_section_content("Module options", sections, md)
        subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE))
        for idx, mod in enumerate(['Pkgconfig', 'Python']):
            mod_subcontents.append(self._get_section_content(f'{mod} module', subsections[idx], content))
        for subcontent in u_subcontents + mod_subcontents:
            # Find the option names
            options = set()
            # Match either a table row or a table heading separator: | ------ |
            rows = re.finditer(r"^\|(?: (\w+) .* | *-+ *)\|", subcontent, re.MULTILINE)
            # Skip the header of the first table
            next(rows)
            # Skip the heading separator of the first table
            next(rows)
            for m in rows:
                value = m.group(1)
                # End when the `buildtype` table starts
                if value is None:
                    break
                options.add(value)
            self.assertEqual(len(found_entries & options), 0)
            found_entries |= options

        # TODO: put the module name back in the OptionKey
        def remove_module_name(key: OptionKey) -> OptionKey:
            if '.' in key.name:
                return key.evolve(name=key.name.split('.', 1)[1])
            return key

        self.assertEqual(found_entries, {
            *(str(remove_module_name(k)) for k in mesonbuild.options.BUILTIN_OPTIONS),
            *(str(remove_module_name(k)) for k in mesonbuild.options.BUILTIN_OPTIONS_PER_MACHINE),
        })

        # Check that `buildtype` table inside `Core options` matches how
        # setting of builtin options behaves
        #
        # Find all tables inside this subsection
        tables = re.finditer(r"^\| (\w+) .* \|\n\| *[-|\s]+ *\|$", u_subcontents[1], re.MULTILINE)
        # Get the table we want using the header of the first column
        table = self._get_section_content('buildtype', tables, u_subcontents[1])
        # Get table row data
        rows = re.finditer(r"^\|(?: (\w+)\s+\| (\w+)\s+\| (\w+) .* | *-+ *)\|", table, re.MULTILINE)
        env = get_fake_env()
        for m in rows:
            buildtype, debug, opt = m.groups()
            if debug == 'true':
                debug = True
            elif debug == 'false':
                debug = False
            else:
                raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}')
            env.coredata.set_option(OptionKey('buildtype'), buildtype)
            self.assertEqual(env.coredata.optstore.get_value('buildtype'), buildtype)
            self.assertEqual(env.coredata.optstore.get_value('optimization'), opt)
            self.assertEqual(env.coredata.optstore.get_value('debug'), debug)

    def test_cpu_families_documented(self):
        with open("docs/markdown/Reference-tables.md", encoding='utf-8') as f:
            md = f.read()
        self.assertIsNotNone(md)

        sections = re.finditer(r"^## (.+)$", md, re.MULTILINE)
        content = self._get_section_content("CPU families", sections, md)
        # Find the list entries
        arches = [m.group(1) for m in re.finditer(r"^\| (\w+) +\|", content, re.MULTILINE)]
        # Drop the header
        arches = set(arches[1:])
        self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families))

    def test_markdown_files_in_sitemap(self):
        '''
        Test that each markdown files in docs/markdown is referenced in sitemap.txt
        '''
        with open("docs/sitemap.txt", encoding='utf-8') as f:
            md = f.read()
        self.assertIsNotNone(md)
        toc = list(m.group(1) for m in re.finditer(r"^\s*(\w.*)$", md, re.MULTILINE))
        markdownfiles = [f.name for f in Path("docs/markdown").iterdir() if f.is_file() and f.suffix == '.md']
        exceptions = ['_Sidebar.md']
        for f in markdownfiles:
            if f not in exceptions and not f.startswith('_include'):
                self.assertIn(f, toc)

    def test_modules_in_navbar(self):
        '''
        Test that each module is referenced in navbar_links.html
        '''
        with open("docs/theme/extra/templates/navbar_links.html", encoding='utf-8') as f:
            html = f.read().lower()
        self.assertIsNotNone(html)
        for f in Path('mesonbuild/modules').glob('*.py'):
            if f.name.startswith('_') or f.name == 'modtest.py':
                continue
            name = f'{f.stem}-module.html'
            name = name.replace('unstable_', '')
            name = name.replace('python3', 'python-3')
            name = name.replace('_', '-')
            self.assertIn(name, html)

    @mock.patch.dict(os.environ)
    @mock.patch.object(Interpreter, 'load_root_meson_file', mock.Mock(return_value=None))
    @mock.patch.object(Interpreter, 'sanity_check_ast', mock.Mock(return_value=None))
    @mock.patch.object(Interpreter, 'parse_project', mock.Mock(return_value=None))
    def test_vim_syntax_highlighting(self):
        '''
        Ensure that vim syntax highlighting files were updated for new
        functions in the global namespace in build files.
        '''
        # Disable unit test specific syntax
        del os.environ['MESON_RUNNING_IN_PROJECT_TESTS']
        env = get_fake_env()
        interp = Interpreter(FakeBuild(env))
        with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f:
            res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE)
            defined = set([a.strip() for a in res.group().split('\\')][1:])
            self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys())))

    @mock.patch.dict(os.environ)
    @mock.patch.object(Interpreter, 'load_root_meson_file', mock.Mock(return_value=None))
    @mock.patch.object(Interpreter, 'sanity_check_ast', mock.Mock(return_value=None))
    @mock.patch.object(Interpreter, 'parse_project', mock.Mock(return_value=None))
    def test_all_functions_defined_in_ast_interpreter(self):
        '''
        Ensure that the all functions defined in the Interpreter are also defined
        in the AstInterpreter (and vice versa).
        '''
        # Disable unit test specific syntax
        del os.environ['MESON_RUNNING_IN_PROJECT_TESTS']
        env = get_fake_env()
        interp = Interpreter(FakeBuild(env))
        astint = AstInterpreter('.', '', '', '', env)
        self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys()))
