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

from .gn import GnBuilder


class ASRApp(Enum):
    ALL_CLUSTERS = auto()
    ALL_CLUSTERS_MINIMAL = auto()
    LIGHT = auto()
    LIGHT_SWITCH = auto()
    LOCK = auto()
    BRIDGE = auto()
    TEMPERATURE_MEASUREMENT = auto()
    THERMOSTAT = auto()
    OTA_REQUESTOR = auto()
    DISHWASHER = auto()

    def ExampleName(self):
        if self == ASRApp.ALL_CLUSTERS:
            return 'all-clusters-app'
        elif self == ASRApp.ALL_CLUSTERS_MINIMAL:
            return 'all-clusters-minimal-app'
        elif self == ASRApp.LIGHT:
            return 'lighting-app'
        elif self == ASRApp.LIGHT_SWITCH:
            return 'light-switch-app'
        elif self == ASRApp.LOCK:
            return 'lock-app'
        elif self == ASRApp.BRIDGE:
            return 'bridge-app'
        elif self == ASRApp.TEMPERATURE_MEASUREMENT:
            return 'temperature-measurement-app'
        elif self == ASRApp.THERMOSTAT:
            return 'thermostat'
        elif self == ASRApp.OTA_REQUESTOR:
            return 'ota-requestor-app'
        elif self == ASRApp.DISHWASHER:
            return 'dishwasher-app'
        else:
            raise Exception('Unknown app type: %r' % self)

    def AppNamePrefix(self):
        if self == ASRApp.ALL_CLUSTERS:
            return 'chip-asr-all-clusters-app'
        elif self == ASRApp.ALL_CLUSTERS_MINIMAL:
            return 'chip-asr-all-clusters-minimal-app'
        elif self == ASRApp.LIGHT:
            return 'chip-asr-lighting-app'
        elif self == ASRApp.LIGHT_SWITCH:
            return 'chip-asr-light-switch-app'
        elif self == ASRApp.LOCK:
            return 'chip-asr-lock-example'
        elif self == ASRApp.BRIDGE:
            return 'chip-asr-bridge-example'
        elif self == ASRApp.TEMPERATURE_MEASUREMENT:
            return 'chip-asr-temperature-measurement-example'
        elif self == ASRApp.THERMOSTAT:
            return 'chip-asr-thermostat-example'
        elif self == ASRApp.OTA_REQUESTOR:
            return 'chip-asr-ota-requestor-example'
        elif self == ASRApp.DISHWASHER:
            return 'chip-asr-dishwasher-example'
        else:
            raise Exception('Unknown app type: %r' % self)

    def BuildRoot(self, root):
        return os.path.join(root, 'examples', self.ExampleName(), 'asr')


class ASRBoard(Enum):
    ASR582X = auto()
    ASR595X = auto()
    ASR550X = auto()

    def GetIC(self):
        if self == ASRBoard.ASR582X:
            return 'asr582x'
        elif self == ASRBoard.ASR595X:
            return 'asr595x'
        elif self == ASRBoard.ASR550X:
            return 'asr550x'
        else:
            raise Exception('Unknown board #: %r' % self)


class ASRBuilder(GnBuilder):

    def __init__(self,
                 root,
                 runner,
                 app: ASRApp = ASRApp.LIGHT,
                 board: ASRBoard = ASRBoard.ASR582X,
                 chip_build_libshell: bool = False,
                 chip_logging: bool = True,
                 enable_factory: bool = False,
                 enable_rotating_device_id: bool = False,
                 enable_ota_requestor: bool = False,
                 enable_lwip_ip6_hook: bool = False):
        super(ASRBuilder, self).__init__(
            root=app.BuildRoot(root),
            runner=runner)

        self.board = board
        self.app = app

        asr_chip = self.board.GetIC()
        self.extra_gn_options = ['asr_ic_family="%s"' % asr_chip]

        if asr_chip == "asr582x":
            ASR_ARCH = "arm"
            ASR_SDK_ROOT = "//third_party/connectedhomeip/third_party/asr/asr582x"
        elif asr_chip == "asr595x":
            ASR_ARCH = "riscv"
            ASR_SDK_ROOT = "//third_party/connectedhomeip/third_party/asr/asr595x"
        elif asr_chip == "asr550x":
            ASR_ARCH = "arm"
            ASR_SDK_ROOT = "//third_party/connectedhomeip/third_party/asr/asr550x"
        self.extra_gn_options.append('target_cpu="%s"' % ASR_ARCH)

        toolchain = os.path.join(root, os.path.split(os.path.realpath(__file__))[0], '../../../config/asr/toolchain')
        toolchain = 'custom_toolchain="{}:asrtoolchain"'.format(toolchain)
        if toolchain:
            self.extra_gn_options.append(toolchain)

        self.extra_gn_options.append('asr_sdk_build_root="%s"' % ASR_SDK_ROOT)
        self.extra_gn_options.append('mbedtls_target="%s:asr_build"' % ASR_SDK_ROOT)

        if (asr_chip == "asr582x"
                or asr_chip == "asr595x"):
            self.extra_gn_options.append('chip_config_network_layer_ble=true')

        if (asr_chip == "asr550x"):
            self.extra_gn_options.append('chip_config_network_layer_ble=false')

        if enable_ota_requestor:
            self.extra_gn_options.append('chip_enable_ota_requestor=true')

        if chip_build_libshell:
            self.extra_gn_options.append('chip_build_libshell=true')

        if chip_logging is False:
            self.extra_gn_options.append('chip_logging=false')

        if enable_factory:
            self.extra_gn_options.append('chip_use_transitional_commissionable_data_provider=false')
            self.extra_gn_options.append('chip_enable_factory_data=true')

        if enable_rotating_device_id:
            self.extra_gn_options.append('chip_enable_additional_data_advertising=true')
            self.extra_gn_options.append('chip_enable_rotating_device_id=true')

        if enable_lwip_ip6_hook:
            self.extra_gn_options.append('chip_lwip_ip6_hook=true')

        self.extra_gn_options.append('asr_toolchain_root="%s"' % os.environ['ASR_TOOLCHAIN_PATH'])

    def GnBuildArgs(self):
        return self.extra_gn_options

    def build_outputs(self):
        items = {
            '%s.out' % self.app.AppNamePrefix():
                os.path.join(self.output_dir, '%s.out' %
                             self.app.AppNamePrefix()),
            '%s.out.map' % self.app.AppNamePrefix():
                os.path.join(self.output_dir,
                             '%s.out.map' % self.app.AppNamePrefix()),
        }

        return items
