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

# Build targets are generally of the form `target + modifiers`
#  - `target` defines the platform-specific application to build. It is often
#    in the form of `platform-board-app` but may be `platform-app` as well
#
#  - `modifiers` are additional compilation options like disabling BLE, enabling
#    coverage or other options that are generally passed into gn configurations
#
# Examples:
#  - linux-x64-chip-tool:  this is a 'chip-tool' build for a 64-bit linux
#  - linux-x64-chip-tool-noble-coverage: a chip tool build with modifiers attached of
#    "noble" and "coverage"
#  - qpg-light: a 'light' app built for qpg
#  - imx-thermostat-release: a 'thermostat` build for imx, with a `release` modifier applied
#
# Interpretation of a specific string of `a-b-c-d`  is left up to the Builder/platform
# as there is no direct convention at this time that an application/variant may not contain
# a `-`. So `a-b-c-d` may for example mean any of:
#   - platform 'a', application 'b', modifiers 'c' and 'd'
#   - platform 'a', board 'b', application 'c-d'
#   - platform 'a', application 'b', modifier 'c-d'
#   - platform 'a', application 'b-c', modifier 'd'
#
# The only requirement of the build system is that a single string corresponds to a single
# combination of platform/board/app/modifier(s). This requirement is unenfornced in code
# but easy enough to follow when defining names for things: just don't reuse names between '-'

import itertools
import logging
import os
import re
from dataclasses import dataclass
from typing import Any, Dict, Iterable, List, Optional

from builders.builder import BuilderOptions

report_rejected_parts = True


@dataclass(init=False)
class TargetPart:
    # SubTarget/Modifier name
    name: str

    # The build arguments to apply to a builder if this part is active
    build_arguments: Dict[str, Any]

    # Part should be included if and only if the final string MATCHES the
    # given regular expression
    only_if_re: Optional[re.Pattern] = None

    # Part should be included if and only if the final string DOES NOT match
    # given regular expression
    except_if_re: Optional[re.Pattern] = None

    def __init__(self, name, **kargs):
        self.name = name.lower()
        self.build_arguments = kargs

    def OnlyIfRe(self, expr: str):
        self.only_if_re = re.compile(expr)
        return self

    def ExceptIfRe(self, expr: str):
        self.except_if_re = re.compile(expr)
        return self

    def Accept(self, full_input: str):
        if self.except_if_re:
            if self.except_if_re.search(full_input):
                if report_rejected_parts:
                    # likely nothing will match when we get such an error
                    logging.error(f"'{self.name}' does not support '{full_input}' due to rule EXCEPT IF '{self.except_if_re.pattern}'")
                return False

        if self.only_if_re:
            if not self.only_if_re.search(full_input):
                if report_rejected_parts:
                    # likely nothing will match when we get such an error
                    logging.error(f"'{self.name}' does not support '{full_input}' due to rule ONLY IF '{self.only_if_re.pattern}'")
                return False

        return True


def _HasVariantPrefix(value: str, prefix: str):
    """Checks if the given value is <prefix> or starts with "<prefix>-".

    This is useful when considering '-'-delimited strings, where a specific
    prefix may either be the last element in the list of items or some first element
    out of several.

    Returns:
        None if no match or the remaining value if there is a match.

    Examples:
        _HasVariantPrefix('foo', 'foo')         # -> ''
        _HasVariantPrefix('foo', 'bar')         # -> None
        _HasVariantPrefix('foo-bar', 'foo')     # -> 'bar'
        _HasVariantPrefix('foo-bar', 'bar')     # -> None
        _HasVariantPrefix('foo-bar-baz', 'foo') # -> 'bar-baz'
        _HasVariantPrefix('foo-bar-baz', 'bar') # -> None
    """
    if value == prefix:
        return ''

    if value.startswith(prefix + '-'):
        return value[len(prefix)+1:]


def _StringIntoParts(full_input: str, remaining_input: str, fixed_targets: List[List[TargetPart]], modifiers: List[TargetPart]):
    """Given an input string, process through all the input rules and return
       the underlying list of target parts for the input.

       Parameters:
          full_input: the full input string, used for validity matching (except/only_if)
          remaining_input: the remaining input to parse
          fixed_targets: the remaining fixed targets left to match
          modifiers: the modifiers left to match
    """
    if not remaining_input:
        if fixed_targets:
            # String was not fully matched. Fixed thargets are required
            return None

        # Fully parsed
        return []

    if fixed_targets:
        # If fixed targets remain, we MUST match one of them
        for target in fixed_targets[0]:
            suffix = _HasVariantPrefix(remaining_input, target.name)
            if suffix is None:
                continue

            # see if match should be rejected. Done AFTER variant prefix detection so we
            # can log if there are issues
            if not target.Accept(full_input):
                continue

            result = _StringIntoParts(full_input, suffix, fixed_targets[1:], modifiers)
            if result is not None:
                return [target] + result

        # None of the variants matched
        return None

    # Only modifiers left to process
    # Process the modifiers one by one
    for modifier in modifiers:
        suffix = _HasVariantPrefix(remaining_input, modifier.name)
        if suffix is None:
            continue

        # see if match should be rejected. Done AFTER variant prefix detection so we
        # can log if there are issues
        if not modifier.Accept(full_input):
            continue

        result = _StringIntoParts(full_input, suffix, fixed_targets[1:], [x for x in modifiers if x != modifier])
        if result is not None:
            return [modifier] + result

    # Remaining input is not empty and we failed to match it
    return None


class BuildTarget:

    def __init__(self, name, builder_class, **kwargs):
        """ Sets up a new build tareget starting with the given builder class
            and initial arguments
        """
        self.name = name.lower()
        self.builder_class = builder_class
        self.create_kw_args = kwargs

        # a list of sub_targets for this builder
        # sub-targets MUST be selected in some way. For example for esp32, we may
        # have a format of esp32-{devkitc, m5stack}-{light,lock}:
        #   - esp32-m5stack-lock is OK
        #   - esp32-devkitc-light is OK
        #   - esp32-light is NOT ok
        #   - esp32-m5stack is NOT ok
        self.fixed_targets: List[List[TargetPart]] = []

        # a list of all available modifiers for this build target
        # Modifiers can be combined in any way
        self.modifiers: List[TargetPart] = []

    def AppendFixedTargets(self, parts: List[TargetPart]):
        """Append a list of potential targets/variants.

        Example:

            target = BuildTarget('linux', LinuxBuilder)
            target.AppendFixedTargets([
                TargetPart(name='x64', board=HostBoard.X64),
                TargetPart(name='x86', board=HostBoard.X86),
                TargetPart(name='arm64', board=HostBoard.ARM64),
            ])

            target.AppendFixedTargets([
                TargetPart(name='light', app=HostApp.LIGHT),
                TargetPart(name='lock', app=HostApp.LIGHT).ExceptIfRe("-arm64-"),
                TargetPart(name='shell', app=HostApp.LIGHT).OnlyIfRe("-(x64|arm64)-"),
            ])

        The above will accept:
           linux-x64-light
           linux-x86-light
           linux-arm64-light
           linux-x64-lock
           linux-x86-lock
           linux-x64-shell
           linux-arm64-shell
        """
        self.fixed_targets.append(parts)

    def AppendModifier(self, name: str, **kargs):
        """Appends a specific modifier to a build target. For example:

        target.AppendModifier(name='release', release=True)
        target.AppendModifier(name='clang', use_clang=True)
        target.AppendModifier(name='coverage', coverage=True).OnlyIfRe('-clang')

        """
        part = TargetPart(name, **kargs)

        self.modifiers.append(part)

        return part

    def HumanString(self):
        """Prints out the human-readable string of the available variants and modifiers:

           like:

           foo-{bar,baz}[-modifier1][modifier2][modifier3]
           foo-bar-{a,b,c}[-m1][-m2]
        """
        result = self.name
        for fixed in self.fixed_targets:
            if len(fixed) > 1:
                result += '-{' + ",".join(map(lambda x: x.name, fixed)) + '}'
            else:
                result += '-' + fixed[0].name

        for modifier in self.modifiers:
            result += f"[-{modifier.name}]"

        return result

    def AllVariants(self) -> Iterable[str]:
        """Returns all possible accepted variants by this target.

           For example name-{a,b}-{c,d}[-1][-2]  could return (there may be Only/ExceptIfRe rules):

              name-a-c
              name-a-c-1
              name-a-c-2
              name-a-c-1-2
              name-a-d
              name-a-d-1
              ...
              name-b-d-2
              name-b-d-1-2

           Notice that this DOES increase exponentially and is potentially a very long list
        """

        # Output is made out of 2 separate parts:
        #   - a valid combination of "fixed parts"
        #   - a combination of modifiers

        fixed_indices = [0]*len(self.fixed_targets)

        while True:

            prefix = "-".join(map(
                lambda p: self.fixed_targets[p[0]][p[1]].name, enumerate(fixed_indices)
            ))

            for n in range(len(self.modifiers) + 1):
                for c in itertools.combinations(self.modifiers, n):
                    suffix = ""
                    for m in c:
                        suffix += "-" + m.name
                    option = f"{self.name}-{prefix}{suffix}"

                    if self.StringIntoTargetParts(option) is not None:
                        yield option

            # Move to the next index in fixed_indices or exit loop if we cannot move
            move_idx = len(fixed_indices) - 1
            while move_idx >= 0:
                if fixed_indices[move_idx] + 1 < len(self.fixed_targets[move_idx]):
                    fixed_indices[move_idx] += 1
                    break

                # need to move the previous value
                fixed_indices[move_idx] = 0
                move_idx -= 1

            if move_idx < 0:
                # done iterating through all
                return

    def StringIntoTargetParts(self, value: str):
        """Given an input string, process through all the input rules and return
           the underlying list of target parts for the input.
        """
        suffix = _HasVariantPrefix(value, self.name)
        if not suffix:
            return None

        return _StringIntoParts(value, suffix, self.fixed_targets, self.modifiers)

    def Create(self, name: str, runner, repository_path: str, output_prefix: str,
               builder_options: BuilderOptions):

        parts = self.StringIntoTargetParts(name)

        if not parts:
            return None

        kargs = {}
        for part in parts:
            kargs.update(part.build_arguments)

        logging.info("Preparing builder '%s'" % (name,))

        builder = self.builder_class(repository_path, runner=runner, **kargs)
        builder.target = self
        builder.identifier = name
        builder.output_dir = os.path.join(output_prefix, name)
        builder.chip_dir = repository_path
        builder.options = builder_options

        return builder
