# Copyright 2020 The Pigweed 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
#
#     https://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.
"""Build a GN target and upload to CIPD."""

from PB.recipes.pigweed.target_to_cipd import InputProperties

DEPS = [
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/cipd_upload',
    'pigweed/environment',
    'pigweed/pw_presubmit',
    'recipe_engine/buildbucket',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/scheduler',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    checkout = api.checkout(props.checkout_options)
    env = api.environment.init(checkout.root, props.environment_options)

    with env():
        if props.artifacts:
            api.build(checkout.root, props.build_options)
            build_dir = api.build.dir
            export_dir = build_dir.join(
                props.pw_presubmit_options.export_dir_name
            )

        else:
            presubmit = api.pw_presubmit.init(
                checkout.root, props.pw_presubmit_options
            )

            # Presubmit steps from this recipe only make sense if there's only
            # one, so complain if there's more than one.
            assert len(presubmit.steps) == 1

            # If using steps we use the entirety of export_dir_name instead of
            # artifact globs.
            assert not props.artifacts

            # OrderedDict.values() is not subscriptable, so iterate over the
            # single value instead of using steps[0].
            for step in presubmit.steps:
                assert step.export_dir
                log_dir = api.path['start_dir'].join('logs')
                api.pw_presubmit.run(presubmit, step, log_dir=log_dir)
                build_dir = step.dir
                export_dir = step.export_dir
                break  # Not required but makes flow clearer at a glance.

    pkg_dir = api.path['start_dir'].join('cipd-package')

    if props.artifacts:
        api.file.ensure_directory('mkdir cipd-package', pkg_dir)

        for glob in props.artifacts:
            with api.step.nest(glob):
                sources = api.file.glob_paths(
                    'glob', api.build.dir, glob, test_data=(glob,)
                )
                if not sources:  # pragma: no cover
                    api.file.listdir('ls build', api.build.dir, recursive=True)
                    raise api.step.StepFailure('no matches for {}'.format(glob))
                for source in sources:
                    with api.step.nest('source') as pres:
                        pres.step_summary_text = '\n'.join(
                            (str(source), str(api.build.dir))
                        )
                        relpath = api.path.relpath(source, api.build.dir)
                        for replacement in props.replacements:
                            relpath = relpath.replace(
                                replacement.old, replacement.new
                            )
                        dest = pkg_dir.join(relpath)
                        pres.step_summary_text += '\n{}'.format(dest)
                    dirname = api.path.dirname(dest)
                    api.file.ensure_directory(
                        'mkdir {}'.format(dirname), dirname
                    )
                    api.file.copy(
                        'copy {} {}'.format(source, dest), source, dest
                    )

    else:
        if api.path.isdir(export_dir):
            api.file.copytree('copy', export_dir, pkg_dir)

    if checkout.options.use_repo:
        api.file.write_text(
            'write manifest',
            pkg_dir.join('manifest.xml'),
            checkout.manifest_snapshot(),
        )

    api.file.listdir('ls package-dir', pkg_dir, recursive=True)

    if not props.dry_run:
        assert checkout.changes
        change = checkout.changes[0]
        search_tag = {'git_revision': change.ref}

        api.cipd_upload(
            cipd_path=props.cipd_path,
            package_root=pkg_dir,
            search_tag=search_tag,
            repository=checkout.options.remote,
            add_platform=props.add_cipd_platform,
        )

        if props.roller_name:
            api.scheduler.emit_trigger(
                api.scheduler.GitilesTrigger(
                    change.remote,
                    'refs/heads/{}'.format(change.branch),
                    change.ref,
                ),
                api.buildbucket.build.builder.project,
                (props.roller_name,),
                'trigger {}'.format(props.roller_name),
            )


def GenTests(api):  # pylint: disable=invalid-name
    yield (
        api.status_check.test('success')
        + api.properties(
            dry_run=False,
            targets=['foo', 'bar'],
            artifacts=['foo/bar/baz'],
            replacements=[{'old': '/bar/', 'new': '/replacement/'}],
            cipd_path='pigweed/cipd/path',
            roller_name='ROLL',
            **api.checkout.repo_properties(),
        )
        + api.checkout.ci_test_data(api.checkout.manifest_repo)
        + api.checkout.manifest_test_data(name='pigweed')
    )

    yield (
        api.status_check.test('pw-presubmit')
        + api.properties(
            dry_run=False,
            cipd_path='pigweed/cipd/path',
            roller_name='ROLL',
            **api.checkout.git_properties(),
        )
        + api.properties(**api.pw_presubmit.properties(step=['step']))
    )
