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

from runner.runner import Runner

from .builder import BuilderOutput, OutDirLock, lock_output_dir
from .gn import Builder

log = logging.getLogger(__name__)


class NuttXApp(Enum):
    LIGHT = auto()

    def ExampleName(self):
        if self == NuttXApp.LIGHT:
            return 'lighting-app'
        raise Exception('Unknown app type: %r' % self)

    def AppNamePrefix(self, chip_name):
        if self == NuttXApp.LIGHT:
            return ('chip-%s-lighting-example' % chip_name)
        raise Exception('Unknown app type: %r' % self)


class NuttXBoard(Enum):
    SIM = auto()

    @property
    def board_config(self):
        # Only one possible board is defined, so return it
        # This can grow if we add more boards
        return 'sim:matter'


class NuttXBuilder(Builder):

    def __init__(self,
                 root: str,
                 runner: Runner,
                 output_dir_lock: OutDirLock,
                 app: NuttXApp = NuttXApp.LIGHT,
                 board: NuttXBoard = NuttXBoard.SIM,
                 ):

        nuttx_chip = 'nuttx'

        super().__init__(
            root=os.path.join(root, 'examples',
                              app.ExampleName(), nuttx_chip),
            runner=runner,
            output_dir_lock=output_dir_lock
        )

        self.chip_name = nuttx_chip
        self.app = app
        self.board = board

    @lock_output_dir
    def generate(self):
        self._Execute(['mkdir', '-p', self.output_dir], title='Preparing output directory for ' + self.identifier)
        nuttx_dir = os.path.join(os.sep, 'opt', 'nuttx', 'nuttx')

        self._Execute(['cmake', '-S', nuttx_dir, '-B', self.output_dir, '-DCHIP_ROOT=' + os.getenv('PW_PROJECT_ROOT'),
                       '-DBOARD_CONFIG=' + self.board.board_config,
                       '-DCMAKE_C_COMPILER=/opt/nuttx/gcc-13/bin/gcc',
                       '-DCMAKE_CXX_COMPILER=/opt/nuttx/gcc-13/bin/g++',
                       '-GNinja'],
                      title='Configuring ' + self.identifier)

    @lock_output_dir
    def _build(self):
        log.info('Compiling NuttX %s at %s, ',
                 self.board.board_config, self.output_dir)
        self._Execute(['cmake', '--build', self.output_dir])

    @lock_output_dir
    def build_outputs(self):
        log.info('Compiling outputs NuttX at %s', self.output_dir)
        extensions = ["out"]
        if self.options.enable_link_map_file:
            extensions.append("out.map")
        for ext in extensions:
            name = f"{self.app.AppNamePrefix(self.chip_name)}.{ext}"
            yield BuilderOutput(os.path.join(self.output_dir, name), name)
