# Copyright 2023 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.
"""

from typing import Generator

from PB.recipe_engine import result
from PB.recipes.pigweed.tokendb_updater import InputProperties, TokenPath
from recipe_engine import recipe_api, recipe_test_api

DEPS = [
    'fuchsia/auto_roller',
    'pigweed/build',
    'pigweed/checkout',
    'pigweed/environment',
    'recipe_engine/file',
    'recipe_engine/properties',
]

PROPERTIES = InputProperties


def RunSteps(
    api: recipe_api.RecipeScriptApi,
    props: InputProperties,
) -> result.RawResult:
    checkout: api.checkout.CheckoutContext = api.checkout(
        props.checkout_options
    )

    env: api.environment.Environment = api.environment.init(
        checkout, props.environment_options
    )
    build: api.build.BuildContext = api.build.create(
        checkout.root, props.build_options
    )

    with env():
        api.build(build)

    for token_path in props.token_paths:
        # Assume if generated is empty that the build wrote to the committed
        # path directly.
        if token_path.generated:
            api.file.copy(
                f'copy <build>/{token_path.generated} '
                f'<checkout>/{token_path.committed}',
                build.root / token_path.generated,
                checkout.root / token_path.committed,
            )

    if not props.auto_roller_options.remote:
        props.auto_roller_options.remote = checkout.options.remote

    change: api.auto_roller.GerritChange = api.auto_roller.attempt_roll(
        props.auto_roller_options,
        repo_dir=checkout.root,
        commit_message=f'[tokendb] Update for {checkout.revision()[0:15]}',
    )

    return api.auto_roller.raw_result(change)


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    def properties(dry_run=False, **kwargs):
        props = InputProperties(**kwargs)
        props.token_paths.extend(
            [
                TokenPath(generated='gen1.csv', committed='tok1.csv'),
                TokenPath(generated='gen2.csv', committed='tok2.csv'),
            ]
        )
        props.checkout_options.CopyFrom(api.checkout.git_options())
        props.build_options.CopyFrom(
            api.build.options(ninja_targets=("gen_tokendb",))
        )
        props.auto_roller_options.CopyFrom(
            api.auto_roller.Options(dry_run=dry_run)
        )
        return api.properties(props)

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

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