# 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.
"""Roll a project in an Android Repo Tool workspace."""

import collections
import re
from typing import Generator
import urllib
import xml.etree.ElementTree

import attrs
from PB.recipes.pigweed.repo_roller import InputProperties
from PB.recipe_modules.pigweed.checkout.options import (
    Options as CheckoutOptions,
)
from recipe_engine import recipe_test_api

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/sso',
    'pigweed/checkout',
    'pigweed/roll_util',
    'recipe_engine/buildbucket',
    'recipe_engine/file',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/raw_io',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


class _TreeBuilder(xml.etree.ElementTree.TreeBuilder):
    def comment(self, data):
        self.start(xml.etree.ElementTree.Comment, {})
        self.data(data)
        self.end(xml.etree.ElementTree.Comment)


def _is_branch(revision):
    """Return True if revision appears to be a branch name."""
    if re.search(r'^[0-9a-fA-F]{40}$', revision):
        return False
    return not revision.startswith('refs/tags/')


# ElementTree orders attributes differently in Python 2 and 3, but if given
# attributes in a specific order it preserves that order.
def _order_attributes(root):
    for el in root.iter():
        if len(el.attrib) > 1:
            new_attrib = sorted(el.attrib.items())
            el.attrib.clear()
            el.attrib.update(new_attrib)


def RunSteps(api, props):  # pylint: disable=invalid-name
    path_to_update = str(props.path_to_update)
    cc_authors_on_rolls = props.cc_authors_on_rolls
    cc_reviewers_on_rolls = props.cc_reviewers_on_rolls
    cc_domains = props.cc_domains
    always_cc = props.always_cc

    props.checkout_options.use_trigger = False
    checkout = api.checkout(props.checkout_options)
    filepath = checkout.root / checkout.options.manifest_file

    new_revision = None

    # Try to get new_revision from the trigger.
    bb_remote = None
    commit = api.buildbucket.build.input.gitiles_commit
    if commit and commit.project:
        new_revision = commit.id
        host = commit.host
        bb_remote = f'https://{host}/{commit.project}'

    tree = _TreeBuilder()
    parser = xml.etree.ElementTree.XMLParser(target=tree)
    parser.feed(api.file.read_text('read manifest', filepath))
    parser.close()
    root = tree.close()

    defaults = {}
    for default in root.findall('default'):
        defaults.update(default.attrib)

    remotes = {}
    for rem in root.findall('remote'):
        remotes[rem.attrib['name']] = rem.attrib

    # Search for path_to_update and check the repository it refers to matches
    # the triggering repository. This check is mostly a config check and
    # shouldn't be triggered in real runs unless somebody moves around project
    # paths in the manifest without updating the builder definition.
    paths_found = []
    proj = None
    proj_attrib = {}
    for proj in root.findall('project'):
        # Sometimes projects don't define something in which case we need to
        # fall back on the remote specified by the project or the default for
        # the entire manifest.
        proj_attrib = {}
        proj_attrib.update(defaults)
        remote_name = proj.attrib.get('remote', defaults.get('remote', None))
        assert remote_name
        proj_attrib.update(remotes[remote_name])
        proj_attrib.update(proj.attrib)
        proj_attrib['fetch'] = api.sso.sso_to_https(proj_attrib['fetch'])

        # Apparently if path is left off name is used. This is mildly
        # infuriating, but easy to work around.
        if 'path' not in proj_attrib:
            proj_attrib['path'] = proj_attrib['name']

        paths_found.append(proj_attrib['path'])
        if proj_attrib['path'] == path_to_update:
            fetch_host = proj_attrib['fetch'].strip('/')
            if fetch_host.startswith('..'):
                parsed = urllib.parse.urlparse(checkout.options.remote)
                fetch_host = (
                    f'{parsed.scheme}://{parsed.netloc}{fetch_host[2:]}'
                )

            manifest_remote = fetch_host + '/' + proj_attrib['name'].strip('/')
            if bb_remote and not checkout.remotes_equivalent(
                manifest_remote, bb_remote
            ):
                raise api.step.StepFailure(
                    "repo paths don't match: {} from manifest "
                    "and {} from buildbucket".format(manifest_remote, bb_remote)
                )
            break

        # Reset proj_attrib to None if this entry wasn't a match, so if this is
        # the last iteration the condition a few lines down will work.
        proj_attrib = {}

    if not proj_attrib:
        raise api.step.StepFailure(
            'cannot find "{}" in manifest (found {})'.format(
                path_to_update, ', '.join('"{}"'.format(x) for x in paths_found)
            )
        )

    if 'upstream' in proj_attrib:
        proj_branch = proj_attrib['upstream']
    elif 'revision' in proj_attrib and _is_branch(proj_attrib['revision']):
        proj_branch = proj_attrib['revision']
    else:
        proj_branch = 'main'

    # If we still don't have a revision then it wasn't in the trigger. (Perhaps
    # this was manually triggered.) In this case we need to determine the
    # latest revision of this repository. The use_trigger flag should have no
    # effect but using it to be explicit. Checking out even if not needed so
    # commit messages can be collected later.
    proj_dir = api.path.start_dir / 'project'
    proj_checkout = api.checkout(
        CheckoutOptions(
            remote=manifest_remote, branch=proj_branch, use_trigger=False
        ),
        root=proj_dir,
    )
    if new_revision is None:
        new_revision = api.checkout.get_revision(proj_dir)

    assert new_revision
    new_revision = str(new_revision)

    # If upstream not set we may be transitioning from tracking a branch to
    # rolling. In that case set upstream to be the revision, but only if the
    # revision appears to be a branch.
    if 'upstream' not in proj_attrib:
        if _is_branch(proj_attrib['revision']):
            # Explicitly update both proj.attrib and proj_attrib to minimize
            # confusion if these statements are moved around later.
            proj.attrib['upstream'] = proj_attrib['revision']
            proj_attrib['upstream'] = proj.attrib['upstream']
        else:
            raise api.step.StepFailure(
                'upstream not set and revision is not a branch, aborting'
            )

    old_revision = proj_attrib['revision']
    # Explicitly update both proj.attrib and proj_attrib to minimize confusion.
    proj_attrib['revision'] = proj.attrib['revision'] = new_revision

    direction = api.roll_util.Direction.FORWARD
    if not _is_branch(old_revision):
        direction = api.roll_util.get_roll_direction(
            proj_dir, old_revision, new_revision
        )

    if not api.roll_util.can_roll(direction):
        api.roll_util.skip_roll_step(
            manifest_remote, old_revision, new_revision
        )
        return

    _order_attributes(root)

    api.file.write_text(
        'write manifest',
        filepath,
        '<?xml version="1.0" encoding="UTF-8"?>\n{}\n'.format(
            xml.etree.ElementTree.tostring(root).decode(),
        ),
    )

    roll = api.roll_util.create_roll(
        project_name=path_to_update,
        old_revision=old_revision,
        new_revision=new_revision,
        proj_dir=proj_dir,
        direction=direction,
    )

    authors = api.roll_util.authors(roll)

    max_commits_for_ccing = props.max_commits_for_ccing or 10
    if len(roll.commits) <= max_commits_for_ccing:
        cc = set()
        if cc_authors_on_rolls:
            cc.update(authors)
        if cc_reviewers_on_rolls:
            cc.update(api.roll_util.reviewers(roll))

        def include_cc(email):
            return api.roll_util.include_cc(
                email, cc_domains, checkout.gerrit_host()
            )

        # include_cc() writes steps, so we want things sorted before calling it.
        cc = sorted(set(cc))
        cc_emails = [x.email for x in cc if include_cc(x)]

        if always_cc:
            props.auto_roller_options.cc_emails.extend(cc_emails)
        else:
            props.auto_roller_options.cc_on_failure_emails.extend(cc_emails)

    author_override = None
    with api.step.nest('authors') as pres:
        pres.step_summary_text = repr(authors)
    if len(authors) == 1 and props.forge_author:
        author_override = attrs.asdict(
            api.roll_util.fake_author(next(iter(authors)))
        )

    # merge auto_roller_options and override_auto_roller_options.
    complete_auto_roller_options = api.roll_util.merge_auto_roller_overrides(
        props.auto_roller_options, props.override_auto_roller_options
    )

    change = api.auto_roller.attempt_roll(
        complete_auto_roller_options,
        repo_dir=checkout.root,
        commit_message=api.roll_util.message(roll),
        author_override=author_override,
    )

    return api.auto_roller.raw_result(change)


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    """Create tests."""

    manifest = 'https://host.googlesource.com/manifest'

    def properties(api, path, dry_run=True, equivalent_remotes=(), **kwargs):
        props = InputProperties(**kwargs)
        props.checkout_options.CopyFrom(
            api.checkout.git_options(
                remote=manifest,
                equivalent_remotes=equivalent_remotes,
                match_branch=True,
            )
        )
        props.forge_author = True
        props.path_to_update = path
        props.auto_roller_options.CopyFrom(
            api.auto_roller.Options(dry_run=dry_run, remote=manifest)
        )

        return api.properties(props)

    def read_step_data():
        return api.step_data(
            'read manifest',
            api.file.read_text(
                """
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <!-- single-line comment -->
  <remote name="foo" fetch="sso://foo" review="sso://foo" />
  <remote name="bar" fetch="sso://bar" review="sso://bar" />
  <remote name="host" fetch=".." review="sso://host" />
  <remote name="dotdot-prefix" fetch="../prefix" review="sso://host/prefix" />
  <remote name="host-prefix" fetch="sso://host/prefix"
    review="sso://host/prefix" />
  <default remote="bar" />
  <project name="a" path="a1" remote="foo"
    revision="1111111111111111111111111111111111111111" upstream="main"/>
  <project name="b" path="b2"
    revision="2222222222222222222222222222222222222222" upstream="main"/>
  <!--
  multi
  line
  comment
  -->
  <project name="c" path="c3" revision="main"/>
  <project name="d" path="d4"
    revision="0000000000111111111122222222223333333333"/>
  <project name="e5" revision="refs/tags/e"/>
  <project name="f" path="f6" remote="host" revision="main"/>
  <project name="g" path="g7" remote="dotdot-prefix" revision="main"/>
  <project name="h" path="h8" remote="host-prefix" revision="main"/>
</manifest>
""".lstrip()
            ),
        )

    def commit_data(name):
        return api.roll_util.commit_data(
            name, api.roll_util.commit('a' * 40, 'foo\nbar')
        )

    yield (
        api.test('success')
        + properties(api, path='a1', cc_authors_on_rolls=True, always_cc=True)
        + api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a')
        + commit_data('a1')
        + read_step_data()
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('name-not-found', status='FAILURE')
        + properties(api, path='missing')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/b')
        + read_step_data()
    )

    yield (
        api.test('equivalent')
        + properties(
            api,
            path='b2',
            equivalent_remotes=(
                (
                    'https://equiv.googlesource.com/b',
                    'https://bar.googlesource.com/b',
                ),
            ),
            cc_reviewers_on_rolls=True,
        )
        + api.checkout.ci_test_data(git_repo='https://equiv.googlesource.com/b')
        + commit_data('b2')
        + read_step_data()
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('upstream-not-set')
        + properties(api, path='c3')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c')
        + commit_data('c3')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('upstream-not-set-revision-not-branch', status='FAILURE')
        + properties(api, path='d4')
        + api.checkout.ci_test_data(git_repo='https://bar.googlesource.com/c')
        + read_step_data()
    )

    yield (
        api.test('no-trigger-with-upstream')
        + properties(api, path='a1')
        + commit_data('a1')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
        + api.roll_util.forward_roll()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('no-trigger-with-revision-branch')
        + properties(api, path='c3')
        + commit_data('c3')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('no-trigger-with-revision-hash', status='FAILURE')
        + properties(api, path='d4')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
    )

    yield (
        api.test('no-trigger-with-revision-tag', status='FAILURE')
        + properties(api, path='e5')
        + read_step_data()
        + api.step_data(
            'git log',
            stdout=api.raw_io.output_text('hash-from-special-checkout'),
        )
    )

    yield (
        api.test('backwards')
        + properties(api, path='a1')
        + api.checkout.ci_test_data(git_repo='https://foo.googlesource.com/a')
        + read_step_data()
        + api.roll_util.backward_roll()
    )

    yield (
        api.test('host-dot-dot')
        + properties(api, path='f6')
        + api.checkout.ci_test_data(git_repo='https://host.googlesource.com/f')
        + commit_data('f6')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('dotdot-prefix')
        + properties(api, path='g7')
        + api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/g'
        )
        + commit_data('g7')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )

    yield (
        api.test('host-prefix')
        + properties(api, path='h8')
        + api.checkout.ci_test_data(
            git_repo='https://host.googlesource.com/prefix/h'
        )
        + commit_data('h8')
        + read_step_data()
        + api.auto_roller.dry_run_success()
    )
