# 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 = [
    'fuchsia/status_check',
    '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.status_check.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.status_check.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.status_check.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.status_check.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('{:040}'.format(i), 'Commit {}'.format(i))
                for i in range(0, 200)
            ],
        )
        + api.roll_util.forward_roll()
        + api.roll_util.not_cancelled()
    )

    yield (
        api.status_check.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.status_check.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.status_check.test('up_to_date')
        + api.properties(
            project_name='proj', old_revision='1' * 40, new_revision='1' * 40
        )
        + api.roll_util.cancelled()
    )

    yield (
        api.status_check.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.status_check.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()
    )
