# 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, CodegenJavaClassPregenerator,
                            CodegenJavaJNIPregenerator)
from .using_zap import ZapApplicationPregenerator


def _IdlsInDirectory(top_directory_name: str, truncate_length: int):
    for root, dirs, files in os.walk(top_directory_name):
        for file in files:
            if file.endswith('.zap'):
                yield InputIdlFile(file_type=IdlFileType.ZAP,
                                   full_path=os.path.join(root, file),
                                   relative_path=os.path.join(root[truncate_length:], file))
            if file.endswith('.matter'):
                yield InputIdlFile(file_type=IdlFileType.MATTER,
                                   full_path=os.path.join(root, file),
                                   relative_path=os.path.join(root[truncate_length:], file))


def _FindAllIdls(sdk_root: str, external_roots: Optional[List[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)

    # first go over SDK items
    for subdir_name in relevant_subdirs:
        top_directory_name = os.path.join(sdk_root, subdir_name)
        logging.debug(f"Searching {top_directory_name}")
        for idl in _IdlsInDirectory(top_directory_name, sdk_root_length+1):
            yield idl

    # next external roots
    if external_roots:
        for root in external_roots:
            root = os.path.normpath(root)
            for idl in _IdlsInDirectory(root, len(root) + 1):
                yield idl


@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, external_roots: Optional[List[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),
        CodegenJavaJNIPregenerator(sdk_root),
        CodegenJavaClassPregenerator(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, external_roots):
        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)
