# 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.
"""Test of rolls of one repository."""

from recipe_engine.config import List
from recipe_engine.recipe_api import Property

DEPS = [
    'pigweed/roll_util',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = {
    'project_name': Property(kind=str),
    'original_commits': Property(kind=List),
    'old_revision': Property(kind=str),
    'new_revision': Property(kind=str),
}


def RunSteps(  # pylint: disable=invalid-name
    api, project_name, old_revision, new_revision
):
    proj_dir = api.path['start_dir'].join('project')

    direction = api.roll_util.get_roll_direction(
        api.path['checkout'], old_revision, new_revision
    )
    if api.roll_util.can_roll(direction):
        roll = api.roll_util.Roll(
            project_name=project_name,
            old_revision=old_revision,
            new_revision=new_revision,
            proj_dir=proj_dir,
            direction=direction,
        )

        def steplog(name, value):
            with api.step.nest(name) as pres:
                pres.step_summary_text = repr(value)

        steplog('remote', roll.remote)
        steplog('gerrit_name', roll.gerrit_name)

        with api.step.nest('emails') as pres:
            pres.logs['authors'] = sorted(
                x.email for x in api.roll_util.authors(roll)
            )
            pres.logs['reviewers'] = sorted(
                x.email for x in api.roll_util.reviewers(roll)
            )

        message = api.roll_util.message(roll)
        with api.step.nest('message') as pres:
            pres.logs['message'] = message

    else:
        api.roll_util.skip_roll_step('remote', old_revision, new_revision)

    host = 'pigweed-review.googlesource.com'

    api.roll_util.can_cc_on_roll('email@example.com', host)
    api.roll_util.can_cc_on_roll('nobody@google.com', host)

    Account = api.roll_util.Account
    user = Account('user', 'user@example.com')

    assert (
        api.roll_util.fake_author(user).email
        == 'user@pigweed.infra.roller.example.com'
    )

    with api.step.nest('CCing'):
        api.roll_util.include_cc(user, ('example.com',), host)
    with api.step.nest('not CCing, domain excluded'):
        api.roll_util.include_cc(user, ('google.com',), host)
    with api.step.nest('not CCing, robot account'):
        api.roll_util.include_cc(
            Account('robot', 'robot@gserviceaccount.com'), (), host,
        )
    with api.step.nest('not CCing, no account in Gerrit'):
        api.roll_util.include_cc(
            Account('nobody', 'nobody@google.com'), (), host,
        )


def GenTests(api):  # pylint: disable=invalid-name
    yield (
        api.test('singlecommit_singleline')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        )
        + api.roll_util.properties(commit_divider='--divider--')
        + api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('1' * 40, 'foo\n\nbar\n\nChange-Id: I11111'),
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.test('singlecommit_multiline')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        )
        + api.roll_util.properties(commit_divider='--divider--')
        + api.roll_util.commit_data(
            'proj',
            api.roll_util.commit(
                '1' * 40,
                'foo  ' * 20
                + '\n\nbar\n\nBug: 123\nCC: foo\nFoo-Auto-Submit: true\n',
            ),
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.test('multicommit')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='4' * 40
        )
        + api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('4' * 40, 'xyz\n\nxyz'),
            api.roll_util.commit('3' * 40, 'baz\n\nbaz'),
            api.roll_util.commit(
                '2' * 40, ''.join(x * 10 for x in '0123456789')
            ),
            api.roll_util.commit('1' * 40, 'foo\n\nfoo'),
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.test('manymanycommit')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='4' * 40
        )
        + api.roll_util.commit_data(
            'proj',
            *[
                api.roll_util.commit(f'{i:040}', f'Commit {i}')
                for i in range(0, 200)
            ],
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.test('frombranch')
        + api.properties(
            project_name='proj', old_revision='main', new_revision='5' * 40
        )
        + api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('5' * 40, 'five'),
            api.roll_util.commit('4' * 40, 'four'),
            api.roll_util.commit('3' * 40, 'three'),
            api.roll_util.commit('2' * 40, 'two'),
            api.roll_util.commit('1' * 40, 'one'),
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.test('backwards')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        )
        + api.roll_util.backward_roll()
        + api.roll_util.cancelled()
    )

    yield (
        api.test('up_to_date')
        + api.properties(
            project_name='proj', old_revision='1' * 40, new_revision='1' * 40
        )
        + api.roll_util.cancelled()
    )

    yield (
        api.test('up_to_date_testonly')
        + api.properties(
            project_name='proj', old_revision='1' * 40, new_revision='2' * 40
        )
        + api.roll_util.noop_roll()
        + api.roll_util.cancelled()
    )

    yield (
        api.test('rebase')
        + api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='5' * 40
        )
        + api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('5' * 40, 'five'),
            api.roll_util.commit('4' * 40, 'four'),
            api.roll_util.commit('3' * 40, 'three'),
            api.roll_util.commit('2' * 40, 'two'),
            api.roll_util.commit('1' * 40, 'one'),
        )
        + api.roll_util.rebased_roll()
        + api.roll_util.not_cancelled()
    )
