# 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


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()
    )
