# Copyright 2020 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.

import pathlib
import pickle
import re
import os
import sys
import typing as T

from ..backend.ninjabackend import TargetDependencyScannerInfo, ninja_quote
from ..compilers.compilers import lang_suffixes

CPP_IMPORT_RE = re.compile(r'\w*import ([a-zA-Z0-9]+);')
CPP_EXPORT_RE = re.compile(r'\w*export module ([a-zA-Z0-9]+);')

FORTRAN_INCLUDE_PAT = r"^\s*include\s*['\"](\w+\.\w+)['\"]"
FORTRAN_MODULE_PAT = r"^\s*\bmodule\b\s+(\w+)\s*(?:!+.*)*$"
FORTRAN_SUBMOD_PAT = r"^\s*\bsubmodule\b\s*\((\w+:?\w+)\)\s*(\w+)"
FORTRAN_USE_PAT = r"^\s*use,?\s*(?:non_intrinsic)?\s*(?:::)?\s*(\w+)"

FORTRAN_MODULE_RE = re.compile(FORTRAN_MODULE_PAT, re.IGNORECASE)
FORTRAN_SUBMOD_RE = re.compile(FORTRAN_SUBMOD_PAT, re.IGNORECASE)
FORTRAN_USE_RE = re.compile(FORTRAN_USE_PAT, re.IGNORECASE)

class DependencyScanner:
    def __init__(self, pickle_file: str, outfile: str, sources: T.List[str]):
        with open(pickle_file, 'rb') as pf:
            self.target_data = pickle.load(pf) # type: TargetDependencyScannerInfo
        self.outfile = outfile
        self.sources = sources
        self.provided_by = {} # type: T.Dict[str, str]
        self.exports = {} # type: T.Dict[str, str]
        self.needs = {} # type: T.Dict[str, T.List[str]]
        self.sources_with_exports = [] # type: T.List[str]

    def scan_file(self, fname: str) -> None:
        suffix = os.path.splitext(fname)[1][1:].lower()
        if suffix in lang_suffixes['fortran']:
            self.scan_fortran_file(fname)
        elif suffix in lang_suffixes['cpp']:
            self.scan_cpp_file(fname)
        else:
            sys.exit(f'Can not scan files with suffix .{suffix}.')

    def scan_fortran_file(self, fname: str) -> None:
        fpath = pathlib.Path(fname)
        modules_in_this_file = set()
        for line in fpath.read_text().split('\n'):
            import_match = FORTRAN_USE_RE.match(line)
            export_match = FORTRAN_MODULE_RE.match(line)
            submodule_export_match = FORTRAN_SUBMOD_RE.match(line)
            if import_match:
                needed = import_match.group(1).lower()
                # In Fortran you have an using declaration also for the module
                # you define in the same file. Prevent circular dependencies.
                if needed not in modules_in_this_file:
                    if fname in self.needs:
                        self.needs[fname].append(needed)
                    else:
                        self.needs[fname] = [needed]
            if export_match:
                exported_module = export_match.group(1).lower()
                assert(exported_module not in modules_in_this_file)
                modules_in_this_file.add(exported_module)
                if exported_module in self.provided_by:
                    raise RuntimeError(f'Multiple files provide module {exported_module}.')
                self.sources_with_exports.append(fname)
                self.provided_by[exported_module] = fname
                self.exports[fname] = exported_module
            if submodule_export_match:
                # Store submodule "Foo" "Bar" as "foo:bar".
                # A submodule declaration can be both an import and an export declaration:
                #
                # submodule (a1:a2) a3
                #  - requires a1@a2.smod
                #  - produces a1@a3.smod
                parent_module_name_full = submodule_export_match.group(1).lower()
                parent_module_name = parent_module_name_full.split(':')[0]
                submodule_name = submodule_export_match.group(2).lower()
                concat_name = f'{parent_module_name}:{submodule_name}'
                self.sources_with_exports.append(fname)
                self.provided_by[concat_name] = fname
                self.exports[fname] = concat_name
                # Fortran requires that the immediate parent module must be built
                # before the current one. Thus:
                #
                # submodule (parent) parent   <- requires parent.mod (really parent.smod, but they are created at the same time)
                # submodule (a1:a2) a3        <- requires a1@a2.smod
                #
                # a3 does not depend on the a1 parent module directly, only transitively.
                if fname in self.needs:
                    self.needs[fname].append(parent_module_name_full)
                else:
                    self.needs[fname] = [parent_module_name_full]


    def scan_cpp_file(self, fname: str) -> None:
        fpath = pathlib.Path(fname)
        for line in fpath.read_text().split('\n'):
            import_match = CPP_IMPORT_RE.match(line)
            export_match = CPP_EXPORT_RE.match(line)
            if import_match:
                needed = import_match.group(1)
                if fname in self.needs:
                    self.needs[fname].append(needed)
                else:
                    self.needs[fname] = [needed]
            if export_match:
                exported_module = export_match.group(1)
                if exported_module in self.provided_by:
                    raise RuntimeError(f'Multiple files provide module {exported_module}.')
                self.sources_with_exports.append(fname)
                self.provided_by[exported_module] = fname
                self.exports[fname] = exported_module

    def objname_for(self, src: str) -> str:
        objname = self.target_data.source2object[src]
        assert(isinstance(objname, str))
        return objname

    def module_name_for(self, src: str) -> str:
        suffix = os.path.splitext(src)[1][1:].lower()
        if suffix in lang_suffixes['fortran']:
            exported = self.exports[src]
            # Module foo:bar goes to a file name foo@bar.smod
            # Module Foo goes to a file name foo.mod
            namebase = exported.replace(':', '@')
            if ':' in exported:
                extension = 'smod'
            else:
                extension = 'mod'
            return os.path.join(self.target_data.private_dir, f'{namebase}.{extension}')
        elif suffix in lang_suffixes['cpp']:
            return '{}.ifc'.format(self.exports[src])
        else:
            raise RuntimeError('Unreachable code.')

    def scan(self) -> int:
        for s in self.sources:
            self.scan_file(s)
        with open(self.outfile, 'w') as ofile:
            ofile.write('ninja_dyndep_version = 1\n')
            for src in self.sources:
                objfilename = self.objname_for(src)
                mods_and_submods_needed = []
                module_files_generated = []
                module_files_needed = []
                if src in self.sources_with_exports:
                    module_files_generated.append(self.module_name_for(src))
                if src in self.needs:
                    for modname in self.needs[src]:
                        if modname not in self.provided_by:
                            # Nothing provides this module, we assume that it
                            # comes from a dependency library somewhere and is
                            # already built by the time this compilation starts.
                            pass
                        else:
                            mods_and_submods_needed.append(modname)

                for modname in mods_and_submods_needed:
                    provider_src = self.provided_by[modname]
                    provider_modfile = self.module_name_for(provider_src)
                    # Prune self-dependencies
                    if provider_src != src:
                        module_files_needed.append(provider_modfile)

                quoted_objfilename = ninja_quote(objfilename, True)
                quoted_module_files_generated = [ninja_quote(x, True) for x in module_files_generated]
                quoted_module_files_needed = [ninja_quote(x, True) for x in module_files_needed]
                if quoted_module_files_generated:
                    mod_gen = '| ' + ' '.join(quoted_module_files_generated)
                else:
                    mod_gen = ''
                if quoted_module_files_needed:
                    mod_dep = '| '  + ' '.join(quoted_module_files_needed)
                else:
                    mod_dep = ''
                build_line = 'build {} {}: dyndep {}'.format(quoted_objfilename,
                                                             mod_gen,
                                                             mod_dep)
                ofile.write(build_line + '\n')
        return 0

def run(args: T.List[str]) -> int:
    pickle_file = args[0]
    outfile = args[1]
    sources = args[2:]
    scanner = DependencyScanner(pickle_file, outfile, sources)
    return scanner.scan()
