# 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(f'Unknown app type: {self!r}')

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


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)
