# Copyright (c) 2019 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0

import argparse
import collections
import os
import re
import textwrap

from west import log
from west.commands import WestCommand
from cmake import run_cmake

class Boards(WestCommand):

    def __init__(self):
        super().__init__(
            'boards',
            # Keep this in sync with the string in west-commands.yml.
            'display information about supported boards',
            'Display information about boards',
            accepts_unknown_args=False)

    def do_add_parser(self, parser_adder):
        default_fmt = '{name} ({arch})'
        parser = parser_adder.add_parser(
            self.name,
            help=self.help,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=self.description,
            epilog=textwrap.dedent('''\
            FORMAT STRINGS

            Boards are listed using a Python 3 format string. Arguments
            to the format string are accessed by name.

            The default format string is:

            "{}"

            The following arguments are available:

            - name: board name
            - arch: board architecture
            '''.format(default_fmt)))

        # Remember to update scripts/west-completion.bash if you add or remove
        # flags
        parser.add_argument('-f', '--format', default=default_fmt,
                            help='''Format string to use to list each board;
                                    see FORMAT STRINGS below.'''),

        return parser

    def do_run(self, args, unknown_args):
        zb = os.environ.get('ZEPHYR_BASE')
        if not zb:
            log.die('Internal error: ZEPHYR_BASE not set in the environment, '
                    'and should have been by the main script')

        cmake_args = ['-DBOARD_ROOT_SPACE_SEPARATED={}'.format(zb),
                      '-P', '{}/cmake/boards.cmake'.format(zb)]
        lines = run_cmake(cmake_args, capture_output=True)
        arch_re = re.compile(r'\s*([\w-]+)\:')
        board_re = re.compile(r'\s*([\w-]+)\s*')
        arch = None
        boards = collections.OrderedDict()
        for line in lines:
            match = arch_re.match(line)
            if match:
                arch = match.group(1)
                boards[arch] = []
                continue
            match = board_re.match(line)
            if match:
                if not arch:
                    log.die('Invalid board output from CMake: {}'.format(lines))
                board = match.group(1)
                boards[arch].append(board)

        for arch in boards:
            for board in boards[arch]:
                try:
                    result = args.format.format(
                        name=board,
                        arch=arch)
                    print(result)
                except KeyError as e:
                    # The raised KeyError seems to just put the first
                    # invalid argument in the args tuple, regardless of
                    # how many unrecognizable keys there were.
                    log.die('unknown key "{}" in format string "{}"'.
                            format(e.args[0], args.format))
