# 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 collections import namedtuple
from .. import mesonlib
from .. import build
from ..mesonlib import listify, OrderedSet
from . import ExtensionModule, ModuleObject, MutableModuleObject
from ..interpreterbase import (
    noPosargs, noKwargs, permittedKwargs,
    InterpreterException, InvalidArguments, InvalidCode, FeatureNew,
)

SourceSetRule = namedtuple('SourceSetRule', 'keys sources if_false sourcesets dependencies extra_deps')
SourceFiles = namedtuple('SourceFiles', 'sources dependencies')

class SourceSet(MutableModuleObject):
    def __init__(self, interpreter):
        super().__init__()
        self.rules = []
        self.subproject = interpreter.subproject
        self.environment = interpreter.environment
        self.subdir = interpreter.subdir
        self.frozen = False
        self.methods.update({
            'add': self.add_method,
            'add_all': self.add_all_method,
            'all_sources': self.all_sources_method,
            'all_dependencies': self.all_dependencies_method,
            'apply': self.apply_method,
        })

    def check_source_files(self, arg, allow_deps):
        sources = []
        deps = []
        for x in arg:
            if isinstance(x, (str, mesonlib.File,
                              build.GeneratedList, build.CustomTarget,
                              build.CustomTargetIndex)):
                sources.append(x)
            elif hasattr(x, 'found'):
                if not allow_deps:
                    msg = 'Dependencies are not allowed in the if_false argument.'
                    raise InvalidArguments(msg)
                deps.append(x)
            else:
                msg = 'Sources must be strings or file-like objects.'
                raise InvalidArguments(msg)
        mesonlib.check_direntry_issues(sources)
        return sources, deps

    def check_conditions(self, arg):
        keys = []
        deps = []
        for x in listify(arg):
            if isinstance(x, str):
                keys.append(x)
            elif hasattr(x, 'found'):
                deps.append(x)
            else:
                raise InvalidArguments('Conditions must be strings or dependency object')
        return keys, deps

    @permittedKwargs(['when', 'if_false', 'if_true'])
    def add_method(self, state, args, kwargs):
        if self.frozen:
            raise InvalidCode('Tried to use \'add\' after querying the source set')
        when = listify(kwargs.get('when', []))
        if_true = listify(kwargs.get('if_true', []))
        if_false = listify(kwargs.get('if_false', []))
        if not when and not if_true and not if_false:
            if_true = args
        elif args:
            raise InterpreterException('add called with both positional and keyword arguments')
        keys, dependencies = self.check_conditions(when)
        sources, extra_deps = self.check_source_files(if_true, True)
        if_false, _ = self.check_source_files(if_false, False)
        self.rules.append(SourceSetRule(keys, sources, if_false, [], dependencies, extra_deps))

    @permittedKwargs(['when', 'if_true'])
    def add_all_method(self, state, args, kwargs):
        if self.frozen:
            raise InvalidCode('Tried to use \'add_all\' after querying the source set')
        when = listify(kwargs.get('when', []))
        if_true = listify(kwargs.get('if_true', []))
        if not when and not if_true:
            if_true = args
        elif args:
            raise InterpreterException('add_all called with both positional and keyword arguments')
        keys, dependencies = self.check_conditions(when)
        for s in if_true:
            if not isinstance(s, SourceSet):
                raise InvalidCode('Arguments to \'add_all\' after the first must be source sets')
            s.frozen = True
        self.rules.append(SourceSetRule(keys, [], [], if_true, dependencies, []))

    def collect(self, enabled_fn, all_sources, into=None):
        if not into:
            into = SourceFiles(OrderedSet(), OrderedSet())
        for entry in self.rules:
            if all(x.found() for x in entry.dependencies) and \
               all(enabled_fn(key) for key in entry.keys):
                into.sources.update(entry.sources)
                into.dependencies.update(entry.dependencies)
                into.dependencies.update(entry.extra_deps)
                for ss in entry.sourcesets:
                    ss.collect(enabled_fn, all_sources, into)
                if not all_sources:
                    continue
            into.sources.update(entry.if_false)
        return into

    @noKwargs
    @noPosargs
    def all_sources_method(self, state, args, kwargs):
        self.frozen = True
        files = self.collect(lambda x: True, True)
        return list(files.sources)

    @noKwargs
    @noPosargs
    @FeatureNew('source_set.all_dependencies() method', '0.52.0')
    def all_dependencies_method(self, state, args, kwargs):
        self.frozen = True
        files = self.collect(lambda x: True, True)
        return list(files.dependencies)

    @permittedKwargs(['strict'])
    def apply_method(self, state, args, kwargs):
        if len(args) != 1:
            raise InterpreterException('Apply takes exactly one argument')
        config_data = args[0]
        self.frozen = True
        strict = kwargs.get('strict', True)
        if isinstance(config_data, dict):
            def _get_from_config_data(key):
                if strict and key not in config_data:
                    raise InterpreterException(f'Entry {key} not in configuration dictionary.')
                return config_data.get(key, False)
        else:
            config_cache = dict()

            def _get_from_config_data(key):
                nonlocal config_cache
                if key not in config_cache:
                    args = [key] if strict else [key, False]
                    config_cache[key] = config_data.get_method(args, {})
                return config_cache[key]

        files = self.collect(_get_from_config_data, False)
        res = SourceFilesObject(files)
        return res

class SourceFilesObject(ModuleObject):
    def __init__(self, files):
        super().__init__()
        self.files = files
        self.methods.update({
            'sources': self.sources_method,
            'dependencies': self.dependencies_method,
        })

    @noPosargs
    @noKwargs
    def sources_method(self, state, args, kwargs):
        return list(self.files.sources)

    @noPosargs
    @noKwargs
    def dependencies_method(self, state, args, kwargs):
        return list(self.files.dependencies)

class SourceSetModule(ExtensionModule):
    @FeatureNew('SourceSet module', '0.51.0')
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.methods.update({
            'source_set': self.source_set,
        })

    @noKwargs
    @noPosargs
    def source_set(self, state, args, kwargs):
        return SourceSet(self.interpreter)

def initialize(*args, **kwargs):
    return SourceSetModule(*args, **kwargs)
