# Copyright 2019 The Meson development team

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .common import CMakeException, CMakeBuildFile, CMakeConfiguration
import typing as T
from .. import mlog
from pathlib import Path
import json
import re

STRIP_KEYS = ['cmake', 'reply', 'backtrace', 'backtraceGraph', 'version']

class CMakeFileAPI:
    def __init__(self, build_dir: Path):
        self.build_dir            = build_dir
        self.api_base_dir         = self.build_dir / '.cmake' / 'api' / 'v1'
        self.request_dir          = self.api_base_dir / 'query' / 'client-meson'
        self.reply_dir            = self.api_base_dir / 'reply'
        self.cmake_sources        = []   # type: T.List[CMakeBuildFile]
        self.cmake_configurations = []   # type: T.List[CMakeConfiguration]
        self.kind_resolver_map    = {
            'codemodel': self._parse_codemodel,
            'cmakeFiles': self._parse_cmakeFiles,
        }

    def get_cmake_sources(self) -> T.List[CMakeBuildFile]:
        return self.cmake_sources

    def get_cmake_configurations(self) -> T.List[CMakeConfiguration]:
        return self.cmake_configurations

    def setup_request(self) -> None:
        self.request_dir.mkdir(parents=True, exist_ok=True)

        query = {
            'requests': [
                {'kind': 'codemodel', 'version': {'major': 2, 'minor': 0}},
                {'kind': 'cmakeFiles', 'version': {'major': 1, 'minor': 0}},
            ]
        }

        query_file = self.request_dir / 'query.json'
        query_file.write_text(json.dumps(query, indent=2))

    def load_reply(self) -> None:
        if not self.reply_dir.is_dir():
            raise CMakeException('No response from the CMake file API')

        root = None
        reg_index = re.compile(r'^index-.*\.json$')
        for i in self.reply_dir.iterdir():
            if reg_index.match(i.name):
                root = i
                break

        if not root:
            raise CMakeException('Failed to find the CMake file API index')

        index = self._reply_file_content(root)   # Load the root index
        index = self._strip_data(index)          # Avoid loading duplicate files
        index = self._resolve_references(index)  # Load everything
        index = self._strip_data(index)          # Strip unused data (again for loaded files)

        # Debug output
        debug_json = self.build_dir / '..' / 'fileAPI.json'
        debug_json = debug_json.resolve()
        debug_json.write_text(json.dumps(index, indent=2))
        mlog.cmd_ci_include(debug_json.as_posix())

        # parse the JSON
        for i in index['objects']:
            assert(isinstance(i, dict))
            assert('kind' in i)
            assert(i['kind'] in self.kind_resolver_map)

            self.kind_resolver_map[i['kind']](i)

    def _parse_codemodel(self, data: T.Dict[str, T.Any]) -> None:
        assert('configurations' in data)
        assert('paths' in data)

        source_dir = data['paths']['source']
        build_dir = data['paths']['build']

        # The file API output differs quite a bit from the server
        # output. It is more flat than the server output and makes
        # heavy use of references. Here these references are
        # resolved and the resulting data structure is identical
        # to the CMake serve output.

        def helper_parse_dir(dir_entry: T.Dict[str, T.Any]) -> T.Tuple[Path, Path]:
            src_dir = Path(dir_entry.get('source', '.'))
            bld_dir = Path(dir_entry.get('build', '.'))
            src_dir = src_dir if src_dir.is_absolute() else source_dir / src_dir
            bld_dir = bld_dir if bld_dir.is_absolute() else build_dir  / bld_dir
            src_dir = src_dir.resolve()
            bld_dir = bld_dir.resolve()

            return src_dir, bld_dir

        def parse_sources(comp_group: T.Dict[str, T.Any], tgt: T.Dict[str, T.Any]) -> T.Tuple[T.List[Path], T.List[Path], T.List[int]]:
            gen = []
            src = []
            idx = []

            src_list_raw = tgt.get('sources', [])
            for i in comp_group.get('sourceIndexes', []):
                if i >= len(src_list_raw) or 'path' not in src_list_raw[i]:
                    continue
                if src_list_raw[i].get('isGenerated', False):
                    gen += [Path(src_list_raw[i]['path'])]
                else:
                    src += [Path(src_list_raw[i]['path'])]
                idx += [i]

            return src, gen, idx

        def parse_target(tgt: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]:
            src_dir, bld_dir = helper_parse_dir(cnf.get('paths', {}))

            # Parse install paths (if present)
            install_paths = []
            if 'install' in tgt:
                prefix = Path(tgt['install']['prefix']['path'])
                install_paths = [prefix / x['path'] for x in tgt['install']['destinations']]
                install_paths = list(set(install_paths))

            # On the first look, it looks really nice that the CMake devs have
            # decided to use arrays for the linker flags. However, this feeling
            # soon turns into despair when you realize that there only one entry
            # per type in most cases, and we still have to do manual string splitting.
            link_flags = []
            link_libs = []
            for i in tgt.get('link', {}).get('commandFragments', []):
                if i['role'] == 'flags':
                    link_flags += [i['fragment']]
                elif i['role'] == 'libraries':
                    link_libs += [i['fragment']]
                elif i['role'] == 'libraryPath':
                    link_flags += ['-L{}'.format(i['fragment'])]
                elif i['role'] == 'frameworkPath':
                    link_flags += ['-F{}'.format(i['fragment'])]
            for i in tgt.get('archive', {}).get('commandFragments', []):
                if i['role'] == 'flags':
                    link_flags += [i['fragment']]

            # TODO The `dependencies` entry is new in the file API.
            #      maybe we can make use of that in addition to the
            #      implicit dependency detection
            tgt_data = {
                'artifacts': [Path(x.get('path', '')) for x in tgt.get('artifacts', [])],
                'sourceDirectory': src_dir,
                'buildDirectory': bld_dir,
                'name': tgt.get('name', ''),
                'fullName': tgt.get('nameOnDisk', ''),
                'hasInstallRule': 'install' in tgt,
                'installPaths': install_paths,
                'linkerLanguage': tgt.get('link', {}).get('language', 'CXX'),
                'linkLibraries': ' '.join(link_libs),  # See previous comment block why we join the array
                'linkFlags': ' '.join(link_flags),     # See previous comment block why we join the array
                'type': tgt.get('type', 'EXECUTABLE'),
                'fileGroups': [],
            }

            processed_src_idx = []
            for cg in tgt.get('compileGroups', []):
                # Again, why an array, when there is usually only one element
                # and arguments are separated with spaces...
                flags = []
                for i in cg.get('compileCommandFragments', []):
                    flags += [i['fragment']]

                cg_data = {
                    'defines': [x.get('define', '') for x in cg.get('defines', [])],
                    'compileFlags': ' '.join(flags),
                    'language': cg.get('language', 'C'),
                    'isGenerated': None,  # Set later, flag is stored per source file
                    'sources': [],
                    'includePath': cg.get('includes', []),
                }

                normal_src, generated_src, src_idx = parse_sources(cg, tgt)
                if normal_src:
                    cg_data = dict(cg_data)
                    cg_data['isGenerated'] = False
                    cg_data['sources'] = normal_src
                    tgt_data['fileGroups'] += [cg_data]
                if generated_src:
                    cg_data = dict(cg_data)
                    cg_data['isGenerated'] = True
                    cg_data['sources'] = generated_src
                    tgt_data['fileGroups'] += [cg_data]
                processed_src_idx += src_idx

            # Object libraries have no compile groups, only source groups.
            # So we add all the source files to a dummy source group that were
            # not found in the previous loop
            normal_src = []
            generated_src = []
            for idx, src in enumerate(tgt.get('sources', [])):
                if idx in processed_src_idx:
                    continue

                if src.get('isGenerated', False):
                    generated_src += [src['path']]
                else:
                    normal_src += [src['path']]

            if normal_src:
                tgt_data['fileGroups'] += [{
                    'isGenerated': False,
                    'sources': normal_src,
                }]
            if generated_src:
                tgt_data['fileGroups'] += [{
                    'isGenerated': True,
                    'sources': generated_src,
                }]
            return tgt_data

        def parse_project(pro: T.Dict[str, T.Any]) -> T.Dict[str, T.Any]:
            # Only look at the first directory specified in directoryIndexes
            # TODO Figure out what the other indexes are there for
            p_src_dir = source_dir
            p_bld_dir = build_dir
            try:
                p_src_dir, p_bld_dir = helper_parse_dir(cnf['directories'][pro['directoryIndexes'][0]])
            except (IndexError, KeyError):
                pass

            pro_data = {
                'name': pro.get('name', ''),
                'sourceDirectory': p_src_dir,
                'buildDirectory': p_bld_dir,
                'targets': [],
            }

            for ref in pro.get('targetIndexes', []):
                tgt = {}
                try:
                    tgt = cnf['targets'][ref]
                except (IndexError, KeyError):
                    pass
                pro_data['targets'] += [parse_target(tgt)]

            return pro_data

        for cnf in data.get('configurations', []):
            cnf_data = {
                'name': cnf.get('name', ''),
                'projects': [],
            }

            for pro in cnf.get('projects', []):
                cnf_data['projects'] += [parse_project(pro)]

            self.cmake_configurations += [CMakeConfiguration(cnf_data)]

    def _parse_cmakeFiles(self, data: T.Dict[str, T.Any]) -> None:
        assert 'inputs' in data
        assert 'paths' in data

        src_dir = Path(data['paths']['source'])

        for i in data['inputs']:
            path = Path(i['path'])
            path = path if path.is_absolute() else src_dir / path
            self.cmake_sources += [CMakeBuildFile(path, i.get('isCMake', False), i.get('isGenerated', False))]

    def _strip_data(self, data: T.Any) -> T.Any:
        if isinstance(data, list):
            for idx, i in enumerate(data):
                data[idx] = self._strip_data(i)

        elif isinstance(data, dict):
            new = {}
            for key, val in data.items():
                if key not in STRIP_KEYS:
                    new[key] = self._strip_data(val)
            data = new

        return data

    def _resolve_references(self, data: T.Any) -> T.Any:
        if isinstance(data, list):
            for idx, i in enumerate(data):
                data[idx] = self._resolve_references(i)

        elif isinstance(data, dict):
            # Check for the "magic" reference entry and insert
            # it into the root data dict
            if 'jsonFile' in data:
                data.update(self._reply_file_content(data['jsonFile']))

            for key, val in data.items():
                data[key] = self._resolve_references(val)

        return data

    def _reply_file_content(self, filename: Path) -> T.Dict[str, T.Any]:
        real_path = self.reply_dir / filename
        if not real_path.exists():
            raise CMakeException(f'File "{real_path}" does not exist')

        data = json.loads(real_path.read_text())
        assert isinstance(data, dict)
        for i in data.keys():
            assert isinstance(i, str)
        return data
