# 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.
"""Update a CIPD package to the latest version."""

import collections
import re

from PB.recipes.pigweed.cipd_roller import InputProperties

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/buildbucket_util',
    'fuchsia/status_check',
    'pigweed/checkout',
    'recipe_engine/buildbucket',
    'recipe_engine/cipd',
    'recipe_engine/file',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

COMMIT_MESSAGE = """
roll: {package_name}

From: {old_version}
To: {new_version}

CQ-Do-Not-Cancel-Tryjobs: true
Build-Errors: continue
""".strip()


def _is_platform(part):
    """Return true for platform-style strings.

    Example matches: "linux-amd64", "${platform}", "${os}-amd64", etc.
    Example non-matches: "clang", "amd64", "linux".
    """
    if '{' in part:
        return True
    try:
        os, arch = part.split('-')
        return os in ('linux', 'mac', 'windows')
    except ValueError:
        return False


def find_shared_tags(api, package_tags, tag):
    """Attempts to find a tag shared by all packages.

    This function can be used if the intersection of the sets of tags
    associated with different-platform packages with the same 'ref' is empty.
    It finds a tag shared by all packages, with as many of them as possible
    matching 'ref'.
    """
    # Find the most common tags.  We use the sorted dict keys for determinism.
    package_paths = sorted(package_tags.keys())
    counter = collections.Counter()
    for path in package_paths:
        counter.update(package_tags[path])
    most_common_tags = counter.most_common()

    with api.step.nest("find shared tag"):
        for tag_candidate, _ in most_common_tags:
            # There is at least one package for which the version with the
            # specified 'ref' does not have this tag. See if there exists a
            # version of this package that *does* have this tag.  If so, use
            # that version.
            updated_tags = dict()
            for package_path in package_paths:
                if tag_candidate in package_tags[package_path]:
                    # For this package we already have a version with this tag,
                    # nothing to do.
                    continue
                try:
                    package_data = api.cipd.describe(
                        package_path, tag_candidate
                    )
                except api.step.StepFailure:
                    # No luck: there exists no version with this tag.
                    break
                updated_tags[package_path] = set(
                    x.tag
                    for x in package_data.tags
                    if x.tag.startswith(tag + ':')
                )
            else:
                # We found a version of each package with the tag_candidate.
                merged_tags = dict()
                merged_tags.update(package_tags)
                merged_tags.update(updated_tags)
                tags = set.intersection(*merged_tags.values())
                # Should always succeed.
                assert len(tags) > 0
                # Update package_tags to be consistent with the returned tags.
                package_tags.update(updated_tags)
                return tags

    # We failed to find any tag that meets our criteria.
    return set()


def RunSteps(api, props):
    cipd_json_path = props.cipd_json_path
    package_name = props.package_name
    package_spec = props.package_spec
    ref = props.ref
    tag = props.tag
    allow_mismatched_refs = props.allow_mismatched_refs

    props.checkout_options.use_trigger = False
    checkout = api.checkout(props.checkout_options)

    cipd_json_path = checkout.root.join(*re.split(r'[\\/]+', cipd_json_path))

    if not package_name:
        # Turn foo/bar/baz/${platform} and foo/bar/baz/${os=mac}-${arch} into
        # 'baz'.
        package_name = [
            part for part in package_spec.split('/') if not _is_platform(part)
        ][-1]

    basename = api.path.basename(cipd_json_path)
    cipd_json = api.file.read_json('read {}'.format(basename), cipd_json_path)
    packages = cipd_json
    if isinstance(cipd_json, dict):
        packages = cipd_json['packages']
    old_version = None
    package = None
    for package in packages:
        if package['path'] == package_spec:
            old_version = package['tags'][0]
            break
    else:
        raise api.step.StepFailure(
            "couldn't find package {} in {}".format(
                package_spec, cipd_json_path
            )
        )

    assert package.get('platforms'), 'platforms empty in json'
    platforms = package.get('platforms')
    base, name = package_spec.rstrip('/').rsplit('/', 1)
    if _is_platform(name):
        package_paths = ['{}/{}'.format(base, x) for x in platforms]
    else:
        package_paths = [package_spec]

    package_tags = {}
    tags = None
    for package_path in package_paths:
        try:
            package_data = api.cipd.describe(package_path, ref)

        except api.step.StepFailure:
            # If we got here this package doesn't have the correct ref. This is
            # likely because it's a new platform for an existing package. In
            # that case ignore this platform when checking that refs agree on
            # package versions. We still need at least one platform to have the
            # ref or the checks below will fail.
            pass

        else:
            package_tags[package_path] = set(
                x.tag for x in package_data.tags if x.tag.startswith(tag + ':')
            )
            if tags is None:
                tags = set(package_tags[package_path])
            else:
                tags.intersection_update(package_tags[package_path])

    if not tags and allow_mismatched_refs:
        # The package with the requested ref has non-overlapping tag values for
        # different platforms.  Try relaxing the requirement that all packages
        # come from the same ref, and see if this allows us to find a set with
        # shared tag values.
        tags = find_shared_tags(api, package_tags, tag)

    with api.step.nest('common tags') as presentation:
        presentation.step_summary_text = '\n'.join(sorted(tags))

    if not tags:
        err_lines = ['no common tags across "{}" refs of packages'.format(ref)]
        for package_path, package_tags in sorted(package_tags.items()):
            err_lines.append('')
            err_lines.append(package_path)
            for tag in package_tags:
                err_lines.append(tag)

        raise api.step.StepFailure('<br>'.join(err_lines))
    # Deterministically pick one of the common tags.
    new_version = sorted(tags)[0]
    package['tags'] = [new_version]

    # Verify there's only one instance of each platform package with this tag.
    with api.step.nest('check number of instances'):
        for package_path in package_paths:
            api.cipd.describe(package_path, new_version)

    with api.step.nest('new_version') as presentation:
        presentation.step_summary_text = new_version

    if old_version in tags:
        with api.step.nest('already up-to-date') as presentation:
            presentation.step_summary_text = (
                'current version {} in common tags'
            ).format(old_version)
        return

    api.file.write_text(
        'write {}'.format(basename),
        cipd_json_path,
        api.json.dumps(cipd_json, indent=2, separators=(',', ': ')) + '\n',
    )

    change = api.auto_roller.attempt_roll(
        props.auto_roller_options,
        repo_dir=api.path.dirname(cipd_json_path),
        commit_message=COMMIT_MESSAGE.format(
            package_name=package_name,
            package_spec=package_spec,
            old_version=old_version,
            new_version=new_version,
            builder=api.buildbucket.builder_name,
            build_id=api.buildbucket_util.id,
        ),
    )

    return api.auto_roller.raw_result(change)


def GenTests(api):  # pylint: disable=invalid-name
    """Create tests."""

    def package(cipd_path, old_version, platforms=None):
        result = {
            'path': cipd_path,
            'tags': [old_version],
            '_comment': 'comments should be preserved',
        }

        if platforms is not None:
            result['platforms'] = list(platforms)

        return result

    def describe(package_path, *tags, **kwargs):
        return api.step_data(
            'cipd describe {}'.format(package_path),
            api.cipd.example_describe(
                package_path,
                test_data_tags=[
                    '{}:{}'.format(name, value) for name, value in tags
                ],
            ),
            **kwargs,
        )

    def no_ref(package_paths):
        res = None
        for package_path in package_paths:
            step = describe(package_path, retcode=1)
            res = res + step if res else step
        return res

    def no_common_tags(package_paths, tagname='git_revision'):
        res = None
        for i, package_path in enumerate(package_paths):
            step = describe(package_path, (tagname, i))
            res = res + step if res else step
        return res

    def multiple_common_tags(package_paths, tagname='git_revision'):
        res = None
        for package_path in package_paths:
            step = describe(
                package_path, (tagname, 1), (tagname, 2), (tagname, 3)
            )
            res = res + step if res else step
        return res

    def relaxing_works(package_paths, tagname='git_revision'):
        return api.step_data(
            'find shared tag.cipd describe {}'.format(package_paths[1]),
            api.cipd.example_describe(
                package_paths[1], test_data_tags=['{}:{}'.format(tagname, 0)],
            ),
        )

    def relaxing_does_not_work(package_paths, tagname='git_revision'):
        # No version of package_paths[1] with hoped-for tag.
        return api.step_data(
            'find shared tag.cipd describe {}'.format(package_paths[0]),
            api.cipd.example_describe(package_paths[0]),
            retcode=1,
        ) + api.step_data(
            'find shared tag.cipd describe {}'.format(package_paths[1]),
            api.cipd.example_describe(package_paths[1]),
            retcode=1,
        )

    def read_file_step_data(package_json_name, *packages):
        return api.step_data(
            'read {}'.format(package_json_name),
            api.file.read_json({'packages': packages}),
        )

    spec = 'pigweed/host_tools/${platform}'
    paths = (
        'pigweed/host_tools/linux-amd64',
        'pigweed/host_tools/windows-amd64',
    )

    def properties(package_spec=spec, dry_run=True, **kwargs):
        new_kwargs = {
            'package_spec': package_spec,
            'ref': 'latest',
            'tag': 'git_revision',
            'cipd_json_path': 'pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json',
        }
        new_kwargs.update(api.checkout.git_properties())
        new_kwargs.setdefault(
            'auto_roller_options',
            {'dry_run': dry_run, 'remote': api.checkout.pigweed_repo,},
        )
        new_kwargs.update(kwargs)
        return api.properties(**new_kwargs)

    yield (
        api.status_check.test('success')
        + properties()
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
        )
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('bad_package_spec', status='failure')
        + properties(package_spec='bad-{}'.format(spec))
        + api.checkout.ci_test_data()
        + read_file_step_data('pigweed.json', package(spec, 'git_revision:123'))
    )

    yield (
        api.status_check.test('no_common_tags', status='failure')
        + properties()
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        + no_common_tags(paths)
    )

    yield (
        api.status_check.test('no_common_tags_but_relaxing_ref_mismatch_helps')
        + properties(allow_mismatched_refs=True)
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        # Package 0 exists at git_revision:0, package 1 at git_revision:1
        + no_common_tags(paths)
        # However, package 1 also exists at git_revision:0, so that revision is
        # good to use.
        + relaxing_works(paths)
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test(
            'no_common_tags_and_relaxing_ref_mismatch_does_not_help',
            status='failure',
        )
        + properties(allow_mismatched_refs=True)
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        # Package 0 exists at git_revision:0, package 1 at git_revision:1
        + no_common_tags(paths)
        # However, package 1 does not exist at git_revision:0.
        + relaxing_does_not_work(paths)
    )

    yield (
        api.status_check.test('multiple_common_tags')
        + properties()
        + api.checkout.ci_test_data()
        + multiple_common_tags(paths)
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:2',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
    )

    yield (
        api.status_check.test('missing_tag')
        + properties()
        + api.checkout.ci_test_data()
        + multiple_common_tags(paths)
        + no_ref(['pigweed/host_tools/fake-amd64'])
        + read_file_step_data(
            'pigweed.json',
            package(
                spec,
                'git_revision:2',
                platforms=('linux-amd64', 'windows-amd64', 'fake-amd64'),
            ),
        )
    )

    no_curly_spec = 'pigweed/host_tools/linux-amd64'
    yield (
        api.status_check.test('no_curlies_in_spec')
        + properties(package_spec=no_curly_spec)
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                no_curly_spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('platform-independent')
        + properties(package_spec='foo/bar/baz')
        + api.checkout.ci_test_data()
        + read_file_step_data(
            'pigweed.json',
            package(
                'foo/bar/baz',
                'git_revision:123',
                platforms=['linux-amd64', 'mac-amd64'],
            ),
        )
        + api.auto_roller.dry_run_success()
    )
