# Copyright 2021 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 the pinned versions of Python packages."""

import re

import attr
from PB.recipes.pigweed.update_python_versions import InputProperties

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/gerrit',
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'pigweed/roll_util',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


def RunSteps(api, props):  # pylint: disable=invalid-name
    checkout = api.checkout(props.checkout_options)
    env = api.environment.init(
        checkout.root, props.environment_options, use_constraint_file=False,
    )

    with env():
        constraint_file = props.path_to_constraint_file
        if not constraint_file:
            api.build.gn_gen(checkout.root, props.build_options)

            # pw_build_PIP_CONSTRAINTS is a GN arg that points to a pip
            # constraint file. For more see
            # https://pigweed.googlesource.com/pigweed/pigweed/+/main/pw_build/python.gni
            gn_args = api.build.get_gn_args(
                checkout_root=checkout.root,
                test_data=[
                    {
                        'name': 'pw_build_PIP_CONSTRAINTS',
                        'current': {'value': ['//foo/bar/constraint.file']},
                    }
                ],
            )
            constraint_file = gn_args['pw_build_PIP_CONSTRAINTS']['current'][
                'value'
            ][0].strip('/')

        assert constraint_file

        # Write list of packages to constraint file.
        cmd = [
            'pw',
            'python-packages',
            'list',
            checkout.root.join(constraint_file),
        ]
        api.step('freeze package list', cmd)

    change = api.auto_roller.attempt_roll(
        gerrit_host=api.gerrit.host_from_remote_url(checkout.options.remote),
        gerrit_project=api.gerrit.project_from_remote_url(
            checkout.options.remote
        ),
        upstream_ref=checkout.options.branch,
        repo_dir=checkout.root,
        commit_message='roll: Update Python package versions',
        dry_run=props.dry_run,
        labels_to_set=api.roll_util.labels_to_set,
        labels_to_wait_on=api.roll_util.labels_to_wait_on,
        bot_commit=props.bot_commit,
    )

    return api.auto_roller.raw_result(change)


def GenTests(api):  # pylint: disable=invalid-name
    def properties(**kwargs):
        new_kwargs = {'dry_run': False}
        new_kwargs.update(api.checkout.git_properties())
        new_kwargs.update(kwargs)
        return api.properties(**new_kwargs)

    yield (
        api.status_check.test('simple')
        + properties()
        + api.auto_roller.success()
    )
