# 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):
    api.checkout()
    env = api.environment.init(api.checkout.root, props.environment_options)

    with env():
        if api.pw_presubmit.has_props():
            api.pw_presubmit.init(api.checkout.root)
            steps = api.pw_presubmit.steps()

            # Presubmit steps from this recipe only make sense if there's only
            # one, so complain if there's more than one.
            assert len(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
            # values instead of using steps[0].
            for step in steps:
                assert step.export_dir
                log_dir = api.path['start_dir'].join('logs')
                api.pw_presubmit.run(step, log_dir=log_dir)
                build_dir = step.dir
                break  # Not required but makes flow clearer at a glance.

        else:
            assert props.artifacts

            api.build(api.checkout.root, props.build_options)
            build_dir = api.build.dir

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

    if not props.artifacts and api.pw_presubmit.export_dir_name:
        export_dir = build_dir.join(api.pw_presubmit.export_dir_name)
        if api.path.isdir(export_dir):
            api.file.copytree('copy', export_dir, pkg_dir)

    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
                    )

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

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

    if not props.dry_run:
        assert api.checkout.changes
        change = api.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=api.checkout.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']))
    )
