# 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 ToDict(self):
        """Converts a TargetPart into a dictionary
        """

        result: Dict[str, str] = {}
        result['name'] = self.name

        build_arguments: Dict[str, str] = {}
        for key, value in self.build_arguments.items():
            build_arguments[key] = str(value)

        result['build_arguments'] = build_arguments

        if self.only_if_re is not None:
            result['only_if_re'] = str(self.only_if_re.pattern)

        if self.except_if_re is not None:
            result['except_if_re'] = str(self.except_if_re.pattern)

        return result


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 ToDict(self):
        """Outputs a parseable description of the available variants
        and modifiers:

            like:

            {
                "name": "foo"
                "shorthand": "foo-bar-baz[-m1]"
                "parts": [
                    {
                        "name": "foo",
                        "build_arguments": {
                            "board": "bar"
                        }
                    }
                    {
                        "name": "baz",
                        "build_arguments": {
                            "app": "foo.baz"
                        }
                    }
                ],
                "modifiers": [
                    {
                        "name": "modifier1",
                        "m1": "True"
                    }
                ]
            }
        """
        return {
            'name': self.name,
            'shorthand': self.HumanString(),
            'parts': [[part.ToDict() for part in target] for target in self.fixed_targets],
            'modifiers': [part.ToDict() for part in self.modifiers]
        }

    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
