# Copyright (c) 2022 Project CHIP Authors
#
# 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 fnmatch
import logging
import os
from dataclasses import dataclass, field
from typing import Iterator, List, Optional

from .types import IdlFileType, InputIdlFile
from .using_codegen import CodegenBridgePregenerator, CodegenCppAppPregenerator, CodegenJavaPregenerator
from .using_zap import ZapApplicationPregenerator


def FindAllIdls(sdk_root: str) -> Iterator[InputIdlFile]:
    relevant_subdirs = [
        'examples',  # all example apps
        'src',      # realistically only controller/data_model
    ]

    while sdk_root.endswith('/'):
        sdk_root = sdk_root[:-1]
    sdk_root_length = len(sdk_root)

    for subdir_name in relevant_subdirs:
        top_directory_name = os.path.join(sdk_root, subdir_name)
        logging.debug(f"Searching {top_directory_name}")
        for root, dirs, files in os.walk(top_directory_name):
            for file in files:
                if file.endswith('.zap'):
                    yield InputIdlFile(file_type=IdlFileType.ZAP,
                                       relative_path=os.path.join(root[sdk_root_length+1:], file))
                if file.endswith('.matter'):
                    yield InputIdlFile(file_type=IdlFileType.MATTER,
                                       relative_path=os.path.join(root[sdk_root_length+1:], file))


@dataclass
class TargetFilter:
    # If set, only the specified files are accepted for codegen
    file_type: Optional[IdlFileType] = None

    # If non-empty only the given paths will be code-generated
    path_glob: List[str] = field(default_factory=list)


# TODO: the build GlobMatcher is more complete by supporting `{}` grouping
#       For now this limited glob seems sufficient.
class GlobMatcher:
    def __init__(self, pattern: str):
        self.pattern = pattern

    def matches(self, s: str):
        return fnmatch.fnmatch(s, self.pattern)


def FindPregenerationTargets(sdk_root: str, filter: TargetFilter, runner):
    """Finds all relevand pre-generation targets in the given
       SDK root.

       Pre-generation targets are based on zap and matter files with options
       on what rules to pregenerate and how.
    """

    generators = [
        # Jinja-based codegen
        CodegenBridgePregenerator(sdk_root),
        CodegenJavaPregenerator(sdk_root),
        CodegenCppAppPregenerator(sdk_root),

        # ZAP codegen
        ZapApplicationPregenerator(sdk_root),
    ]

    path_matchers = [GlobMatcher(pattern) for pattern in filter.path_glob]

    for idl in FindAllIdls(sdk_root):
        if filter.file_type is not None:
            if idl.file_type != filter.file_type:
                logging.debug(f"Will not process file of type {idl.file_type}: {idl.relative_path}")
                continue

        if path_matchers:
            if all([not matcher.matches(idl.relative_path) for matcher in path_matchers]):
                logging.debug(f"Glob not matched for {idl.relative_path}")
                continue

        for generator in generators:
            if generator.Accept(idl):
                yield generator.CreateTarget(idl, runner=runner)
