# 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 tokenizer database.

Note: this is not what most developers think of when they see "tokenizer". For
details see https://pigweed.dev/pw_tokenizer/.

On its face builders using this recipe could create infinite loops but they
won't because the changes created by this recipe won't cause changes in the
generated database.
"""

import re

import attr
from PB.recipes.pigweed.tokendb_updater import InputProperties
from PB.recipe_modules.pigweed.checkout.options import (
    Options as CheckoutOptions,
)

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/git',
    'fuchsia/status_check',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'pigweed/roll_util',
    'recipe_engine/context',
    'recipe_engine/file',
    'recipe_engine/path',
    '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)

    tokendb_branch = props.tokendb_branch or "main"
    generated_tokendb_path = checkout.root.join(
        *re.split(r'/+', props.generated_tokendb_path)
    )

    if props.tokendb_host and props.tokendb_project:
        directory = (
            api.path.abs_to_path(
                api.path.split(api.path.abspath(generated_tokendb_path))[0]
            )
            or checkout.root
        )
        with api.step.nest('update token db repo'), api.context(cwd=directory):
            api.git.fetch('origin', tokendb_branch)
            api.git('checkout FETCH_HEAD', 'checkout', 'FETCH_HEAD')

    if bool(props.tokendb_host) != bool(props.tokendb_project):
        raise ValueError(  # pragma: no cover
            'tokendb_host ({}) and tokendb_project ({}) must both be set '
            'or both be empty'.format(props.tokendb_host, props.tokendb_project)
        )

    tokendb_host = checkout.gerrit_host().replace('-review.', '.')
    if props.tokendb_host:
        tokendb_host = '{}.googlesource.com'.format(props.tokendb_host)
    tokendb_project = props.tokendb_project or checkout.gerrit_project()
    tokendb_remote = 'https://{}/{}'.format(
        tokendb_host.rstrip('/'), tokendb_project.strip('/')
    )

    # If the token database is in the top-level repo we just use that. If not
    # we need to checkout the repo even though it's already in our checkout.
    # It's much simpler to do a new checkout instead of parsing .gitmodules.
    tokendb_repo = checkout.root
    tokendb_branch = checkout.options.branch

    if props.tokendb_host and props.tokendb_project:
        tokendb_repo = api.path['start_dir'].join('tokendb')
        tokendb_branch = props.tokendb_branch or "main"
        api.checkout(
            CheckoutOptions(
                remote=tokendb_remote, branch=tokendb_branch, use_trigger=False
            ),
            root=tokendb_repo,
        )

    env = api.environment.init(checkout.root, props.environment_options)

    with env():
        api.build(checkout.root, props.build_options)

    tokendb_path = tokendb_repo.join(*re.split(r'/+', props.tokendb_path))

    if generated_tokendb_path != tokendb_path:
        api.file.copy('copy', generated_tokendb_path, tokendb_path)

    message = 'Update token db for commit {}'.format(checkout.revision()[0:15])

    change = api.auto_roller.attempt_roll(
        api.auto_roller.Options(
            remote=tokendb_remote,
            upstream_ref=tokendb_branch,
            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,
        ),
        repo_dir=tokendb_repo,
        commit_message=message,
    )

    return api.auto_roller.raw_result(change)


def GenTests(api):  # pylint: disable=invalid-name
    def properties(**kwargs):
        new_kwargs = {
            'steps': ['default'],
            'generated_tokendb_path': 'folder/generated.csv',
            'tokendb_path': 'tokendb.csv',
            '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()
    )

    yield (
        api.status_check.test('dry-run')
        + properties(dry_run=True)
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.status_check.test('separate-repo')
        + properties(tokendb_host='pigweed', tokendb_project='tokendb')
        + api.auto_roller.success()
    )
