# 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

PYTHON_VERSION_COMPATIBILITY = "PY3"


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']))
    )
