#!/usr/bin/env -S python3 -B

# Copyright (c) 2021 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
import sys

import click
import coloredlogs

import build
from glob_matcher import GlobMatcher
from runner import PrintOnlyRunner, ShellRunner

sys.path.append(os.path.abspath(os.path.dirname(__file__)))


# Supported log levels, mapping string values required for argument
# parsing into logging constants
__LOG_LEVELS__ = {
    'debug': logging.DEBUG,
    'info': logging.INFO,
    'warn': logging.WARN,
    'fatal': logging.FATAL,
}


def CommaSeparate(items) -> str:
    return ', '.join([x for x in items])


def ValidateRepoPath(context, parameter, value):
    """
    Validates that the given path looks like a valid chip repository checkout.
    """
    if value.startswith('/TEST/'):
        # Hackish command to allow for unit testing
        return value

    for name in ['BUILD.gn', '.gn', os.path.join('scripts', 'bootstrap.sh')]:
        expected_file = os.path.join(value, name)
        if not os.path.exists(expected_file):
            raise click.BadParameter(
                ("'%s' does not look like a valid repository path: "
                 "%s not found.") % (value, expected_file))
    return value


@click.group(chain=True)
@click.option(
    '--log-level',
    default='INFO',
    type=click.Choice(__LOG_LEVELS__.keys(), case_sensitive=False),
    help='Determines the verbosity of script output.')
@click.option(
    '--target',
    default=['all'],
    type=click.Choice(
        ['all'] + [t.name for t in build.ALL_TARGETS], case_sensitive=False),
    multiple=True,
    help='Build target(s). Note that "all" includes glob blacklisted targets'
)
@click.option(
    '--target-glob',
    default=None,
    help='Glob matching for targets to include'
)
@click.option(
    '--skip-target-glob',
    default=None,
    help='Glob matching for targets to explicitly exclude'
)
@click.option(
    '--enable-flashbundle',
    default=False,
    is_flag=True,
    help='Also generate the flashbundles for the app.'
)
@click.option(
    '--repo',
    default='.',
    callback=ValidateRepoPath,
    help='Path to the root of the CHIP SDK repository checkout.')
@click.option(
    '--out-prefix',
    default='./out',
    type=click.Path(file_okay=False, resolve_path=True),
    help='Prefix for the generated file output.')
@click.option(
    '--clean',
    default=False,
    is_flag=True,
    help='Clean output directory before running the command')
@click.option(
    '--dry-run',
    default=False,
    is_flag=True,
    help='Only print out shell commands that would be executed')
@click.option(
    '--dry-run-output',
    default="-",
    type=click.File("wt"),
    help='Where to write the dry run output')
@click.option(
    '--no-log-timestamps',
    default=False,
    is_flag=True,
    help='Skip timestaps in log output')
@click.pass_context
def main(context, log_level, target, target_glob, skip_target_glob, repo,
         out_prefix, clean, dry_run, dry_run_output, enable_flashbundle,
         no_log_timestamps):
    # Ensures somewhat pretty logging of what is going on
    log_fmt = '%(asctime)s %(levelname)-7s %(message)s'
    if no_log_timestamps:
        log_fmt = '%(levelname)-7s %(message)s'
    coloredlogs.install(level=__LOG_LEVELS__[log_level], fmt=log_fmt)

    if 'PW_PROJECT_ROOT' not in os.environ:
        raise click.UsageError("""
PW_PROJECT_ROOT not set in the current environment.

Please make sure you `source scripts/bootstrap.sh` or `source scripts/activate.sh`
before running this script.
""".strip())

    if dry_run:
        runner = PrintOnlyRunner(dry_run_output, root=repo)
    else:
        runner = ShellRunner(root=repo)

    if 'all' in target:
        # NOTE: The "all" target includes things that are glob blacklisted
        #       (so that 'targets' works and displays all)
        targets = build.ALL_TARGETS
    else:
        requested_targets = set([t.lower for t in target])
        targets = [
            target for target in build.ALL_TARGETS
            if target.name.lower in requested_targets
        ]

        actual_targes = set([t.name.lower for t in targets])
        if requested_targets != actual_targes:
            logging.error('Targets not found: %s',
                          CommaSeparate(actual_targes))

    if target_glob:
        matcher = GlobMatcher(target_glob)
        targets = [t for t in targets if matcher.matches(
            t.name) and not t.IsGlobBlacklisted]

    if skip_target_glob:
        matcher = GlobMatcher(skip_target_glob)
        targets = [t for t in targets if not matcher.matches(t.name)]

    # force consistent sorting
    targets.sort(key=lambda t: t.name)
    logging.info('Building targets: %s',
                 CommaSeparate([t.name for t in targets]))

    context.obj = build.Context(
        repository_path=repo, output_prefix=out_prefix, runner=runner)
    context.obj.SetupBuilders(
        targets=targets, enable_flashbundle=enable_flashbundle)

    if clean:
        context.obj.CleanOutputDirectories()


@main.command(
    'gen', help='Generate ninja/makefiles (but does not run the compilation)')
@click.pass_context
def cmd_generate(context):
    context.obj.Generate()


@main.command(
    'targets',
    help=('List the targets that would be generated/built given '
          'the input arguments'))
@click.pass_context
def cmd_targets(context):
    for builder in context.obj.builders:
        if builder.target.IsGlobBlacklisted:
            print("%s (NOGLOB: %s)" %
                  (builder.target.name, builder.target.GlobBlacklistReason))
        else:
            print(builder.target.name)


@main.command('build', help='generate and run ninja/make as needed to compile')
@click.option(
    '--copy-artifacts-to',
    default=None,
    type=click.Path(file_okay=False, resolve_path=True),
    help='Prefix for the generated file output.')
@click.option(
    '--create-archives',
    default=None,
    type=click.Path(file_okay=False, resolve_path=True),
    help='Prefix of compressed archives of the generated files.')
@click.pass_context
def cmd_build(context, copy_artifacts_to, create_archives):
    context.obj.Build()

    if copy_artifacts_to:
        context.obj.CopyArtifactsTo(copy_artifacts_to)

    if create_archives:
        context.obj.CreateArtifactArchives(create_archives)


if __name__ == '__main__':
    main()
