# Copyright (c) 2021-2023 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 contextlib
import logging
import os
import shlex
from enum import Enum, auto

from runner.runner import Runner

from .builder import Builder, BuilderOutput, OutDirLock, lock_output_dir

log = logging.getLogger(__name__)


class Esp32Board(Enum):
    DevKitC = auto()
    M5Stack = auto()
    C3DevKit = auto()
    P4FunctionEV = auto()
    QEMU = auto()


class Esp32App(Enum):
    ALL_CLUSTERS = auto()
    ALL_CLUSTERS_MINIMAL = auto()
    ALL_DEVICES = auto()
    ENERGY_GATEWAY = auto()
    EVSE = auto()
    WATER_HEATER = auto()
    LIGHT = auto()
    LOCK = auto()
    SHELL = auto()
    BRIDGE = auto()
    TEMPERATURE_MEASUREMENT = auto()
    TESTS = auto()
    OTA_REQUESTOR = auto()
    OTA_PROVIDER = auto()

    @property
    def ExamplePath(self):
        if self == Esp32App.ALL_CLUSTERS:
            return 'examples/all-clusters-app'
        if self == Esp32App.ALL_DEVICES:
            return 'examples/all-devices-app'
        if self == Esp32App.ALL_CLUSTERS_MINIMAL:
            return 'examples/all-clusters-minimal-app'
        if self == Esp32App.ENERGY_GATEWAY:
            return 'examples/energy-gateway-app'
        if self == Esp32App.EVSE:
            return 'examples/evse-app'
        if self == Esp32App.WATER_HEATER:
            return 'examples/water-heater-app'
        if self == Esp32App.LIGHT:
            return 'examples/lighting-app'
        if self == Esp32App.LOCK:
            return 'examples/lock-app'
        if self == Esp32App.SHELL:
            return 'examples/shell'
        if self == Esp32App.BRIDGE:
            return 'examples/bridge-app'
        if self == Esp32App.TEMPERATURE_MEASUREMENT:
            return 'examples/temperature-measurement-app'
        if self == Esp32App.OTA_REQUESTOR:
            return 'examples/ota-requestor-app'
        if self == Esp32App.OTA_PROVIDER:
            return 'examples/ota-provider-app'
        if self == Esp32App.TESTS:
            return 'src/test_driver'
        raise Exception('Unknown app type: %r' % self)

    @property
    def AppNamePrefix(self):
        if self == Esp32App.ALL_CLUSTERS:
            return 'chip-all-clusters-app'
        if self == Esp32App.ALL_CLUSTERS_MINIMAL:
            return 'chip-all-clusters-minimal-app'
        if self == Esp32App.ALL_DEVICES:
            return 'all-devices-app'
        if self == Esp32App.ENERGY_GATEWAY:
            return 'chip-energy-gateway-app'
        if self == Esp32App.EVSE:
            return 'chip-evse-app'
        if self == Esp32App.WATER_HEATER:
            return 'matter-water-heater-app'
        if self == Esp32App.LIGHT:
            return 'chip-lighting-app'
        if self == Esp32App.LOCK:
            return 'chip-lock-app'
        if self == Esp32App.SHELL:
            return 'chip-shell'
        if self == Esp32App.BRIDGE:
            return 'chip-bridge-app'
        if self == Esp32App.TEMPERATURE_MEASUREMENT:
            return 'chip-temperature-measurement-app'
        if self == Esp32App.OTA_REQUESTOR:
            return 'chip-ota-requestor-app'
        if self == Esp32App.OTA_PROVIDER:
            return 'chip-ota-provider-app'
        if self == Esp32App.TESTS:
            return None
        raise Exception('Unknown app type: %r' % self)

    def FlashBundleName(self, is_all_devices_selective):
        if not self.AppNamePrefix:
            return None

        if self == Esp32App.ALL_DEVICES and is_all_devices_selective:
            return 'example-device-app.flashbundle.txt'

        return self.AppNamePrefix + '.flashbundle.txt'

    def IsCompatible(self, board: Esp32Board):
        if board == Esp32Board.QEMU:
            return self == Esp32App.TESTS
        if board == Esp32Board.C3DevKit:
            return self == Esp32App.ALL_CLUSTERS or self == Esp32App.ALL_CLUSTERS_MINIMAL
        if board == Esp32Board.P4FunctionEV:
            return self == Esp32App.ALL_CLUSTERS
        return (board in {Esp32Board.M5Stack, Esp32Board.DevKitC}) and (self != Esp32App.TESTS)


def DefaultsFileName(board: Esp32Board, app: Esp32App, enable_rpcs: bool):
    rpc_enabled_apps = {Esp32App.ALL_CLUSTERS,
                        Esp32App.ALL_CLUSTERS_MINIMAL,
                        Esp32App.LIGHT,
                        Esp32App.OTA_REQUESTOR,
                        Esp32App.OTA_PROVIDER,
                        Esp32App.TEMPERATURE_MEASUREMENT}
    if app == Esp32App.TESTS:
        return 'sdkconfig_qemu.defaults'
    if app not in rpc_enabled_apps:
        return 'sdkconfig.defaults'

    rpc = "_rpc" if enable_rpcs else ""
    if board == Esp32Board.DevKitC or board == Esp32Board.C3DevKit or board == Esp32Board.P4FunctionEV:
        return 'sdkconfig{}.defaults'.format(rpc)
    if board == Esp32Board.M5Stack:
        # a subset of apps have m5stack specific configurations. However others
        # just compile for the same devices as aDevKitC
        specific_apps = {
            Esp32App.ALL_CLUSTERS,
            Esp32App.ALL_CLUSTERS_MINIMAL,
            Esp32App.LIGHT,
            Esp32App.OTA_REQUESTOR,
        }
        if app in specific_apps:
            return 'sdkconfig_m5stack{}.defaults'.format(rpc)
        return 'sdkconfig{}.defaults'.format(rpc)
    raise Exception('Unknown board type')


class Esp32Builder(Builder):

    def __init__(self,
                 root: str,
                 runner: Runner,
                 output_dir_lock: OutDirLock,
                 board: Esp32Board = Esp32Board.M5Stack,
                 app: Esp32App = Esp32App.ALL_CLUSTERS,
                 enable_rpcs: bool = False,
                 enable_ipv4: bool = True,
                 enable_insights_trace: bool = False,
                 all_devices_enabled_devices=None,
                 ):
        super().__init__(root, runner, output_dir_lock)
        self.board = board
        self.app = app
        self.enable_rpcs = enable_rpcs
        self.enable_ipv4 = enable_ipv4
        self.enable_insights_trace = enable_insights_trace
        self.all_devices_enabled_devices = all_devices_enabled_devices or []

        if not app.IsCompatible(board):
            raise Exception(
                "Incompatible app/board combination: %r and %r", app, board)

    def _IdfEnvExecute(self, cmd, title=None):
        # Run activate.sh after export.sh to ensure using the chip environment.
        self._Execute(
            ['bash', '-c', 'source $IDF_PATH/export.sh; source scripts/activate.sh; %s' % cmd],
            title=title)

    @property
    def TargetName(self):
        if self.board == Esp32Board.C3DevKit:
            return 'esp32c3'
        if self.board == Esp32Board.P4FunctionEV:
            return 'esp32p4'
        return 'esp32'

    @property
    def TargetFileName(self) -> str | None:
        if self.board == Esp32Board.C3DevKit:
            return 'sdkconfig.defaults.esp32c3'
        if self.board == Esp32Board.P4FunctionEV:
            return 'sdkconfig.defaults.esp32p4'
        return None

    @property
    def ExamplePath(self):
        return os.path.join(self.app.ExamplePath, 'esp32')

    @lock_output_dir
    def generate(self):
        if os.path.exists(os.path.join(self.output_dir, 'build.ninja')):
            return

        example_lock = self.output_dir_lock.lock_dir(
            os.path.join(self.root, self.ExamplePath)) if self.output_dir_lock else contextlib.nullcontext()
        with example_lock:
            defaults = os.path.join(self.ExamplePath, DefaultsFileName(
                self.board, self.app, self.enable_rpcs))

            if not self._runner.dry_run and not os.path.exists(defaults):
                raise Exception('SDK defaults file missing: %s' % defaults)

            defaults_out = os.path.join(self.output_dir, 'sdkconfig.defaults')

            self._Execute(['mkdir', '-p', self.output_dir],
                          title='Generating ' + self.identifier)
            self._Execute(['cp', defaults, defaults_out])
            self._Execute(
                ['rm', '-f', os.path.join(self.ExamplePath, 'sdkconfig')])

            if self.TargetFileName is not None:
                target_defaults = os.path.join(self.ExamplePath, self.TargetFileName)
                if os.path.exists(target_defaults):
                    self._Execute(['cp', target_defaults, os.path.join(self.output_dir, self.TargetFileName)])

            if not self.enable_ipv4:
                self._Execute(
                    ['bash', '-c', 'echo -e "\\nCONFIG_DISABLE_IPV4=y\\n" >>%s' % shlex.quote(defaults_out)])
                self._Execute(
                    ['bash', '-c', 'echo -e "\\nCONFIG_LWIP_IPV4=n\\n" >>%s' % shlex.quote(defaults_out)])

            if self.enable_insights_trace:
                insights_flag = 'y'
            else:
                insights_flag = 'n'

            # pre-requisite
            self._Execute(
                ['bash', '-c', 'echo -e "\\nCONFIG_ESP_INSIGHTS_ENABLED=%s\\nCONFIG_CHIP_ENABLE_ESP_DIAGNOSTICS=%s\\n" >>%s' % (insights_flag, insights_flag, shlex.quote(defaults_out))])

            cmake_flags = []

            if self.options.pregen_dir:
                cmake_flags.append(
                    f"-DCHIP_CODEGEN_PREGEN_DIR={shlex.quote(self.options.pregen_dir)}")

            if self.all_devices_enabled_devices:
                cmake_flags.append(
                    f"-DALL_DEVICES_ENABLED_DEVICES={shlex.quote(';'.join(self.all_devices_enabled_devices))}")

            cmake_args = ['-C', self.ExamplePath, '-B',
                          shlex.quote(self.output_dir)] + cmake_flags

            cmake_args = " ".join(cmake_args)
            defaults = shlex.quote(defaults_out)
            target = shlex.quote(self.TargetName)

            cmd = f"\nexport SDKCONFIG_DEFAULTS={defaults}\nidf.py {cmake_args} -DIDF_TARGET={target} reconfigure"

            # This will do a 'cmake reconfigure' which will create ninja files without rebuilding
            self._IdfEnvExecute(cmd)

    @lock_output_dir
    def _build(self):
        log.info('Compiling Esp32 at %s', self.output_dir)

        example_lock = self.output_dir_lock.lock_dir(
            os.path.join(self.root, self.ExamplePath)) if self.output_dir_lock else contextlib.nullcontext()
        with example_lock:
            # Unfortunately sdkconfig is sticky and needs reset on every build
            self._Execute(
                ['rm', '-f', os.path.join(self.ExamplePath, 'sdkconfig')])

            defaults_out = os.path.join(self.output_dir, 'sdkconfig.defaults')

            # "ninja -C" is insufficient because sdkconfig changes on every 'config' and results
            # in a full reconfiguration with default values
            #
            # This does a regen + reconfigure.
            cmd = "\nexport SDKCONFIG_DEFAULTS={defaults}\nidf.py -C {example_path} -B {out} build".format(
                defaults=shlex.quote(defaults_out),
                example_path=self.ExamplePath,
                out=shlex.quote(self.output_dir)
            )

            self._IdfEnvExecute(cmd, title='Building ' + self.identifier)

    def _AllDevicesOutputName(self):
        """Return the binary base name produced by the all-devices-app build."""
        if self.all_devices_enabled_devices:
            # this builder does not support altering the name
            return 'example-device-app'
        return 'all-devices-app'

    @lock_output_dir
    def build_outputs(self):
        if self.app == Esp32App.TESTS:
            # Include the runnable image names as artifacts
            with open(os.path.join(self.output_dir, 'test_images.txt')) as f:
                for name in filter(None, [x.strip() for x in f.readlines()]):
                    yield BuilderOutput(os.path.join(self.output_dir, name), name)
            return

        extensions = ["elf"]
        if self.options.enable_link_map_file:
            extensions.append("map")
        app_name = self._AllDevicesOutputName() if self.app == Esp32App.ALL_DEVICES else self.app.AppNamePrefix
        for ext in extensions:
            name = f"{app_name}.{ext}"
            yield BuilderOutput(os.path.join(self.output_dir, name), name)

    @lock_output_dir
    def bundle_outputs(self):
        flash_bundle_name = self.app.FlashBundleName(self.all_devices_enabled_devices)
        if not flash_bundle_name:
            return
        with open(os.path.join(self.output_dir, flash_bundle_name)) as f:
            for line in filter(None, [x.strip() for x in f.readlines()]):
                yield BuilderOutput(os.path.join(self.output_dir, line), line)
