# 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
import urllib
import xml.etree.ElementTree

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

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/sso',
    'fuchsia/status_check',
    '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)
    dry_run = props.dry_run
    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.join(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 = 'https://{}/{}'.format(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 = '{}://{}{}'.format(
                    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'].join('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.Roll(
        project_name=path_to_update,
        old_revision=old_revision,
        new_revision=new_revision,
        proj_dir=proj_dir,
        direction=direction,
    )

    cc = set()
    authors = api.roll_util.authors(roll)
    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)]

    roll_kwargs = {}
    if always_cc:
        roll_kwargs['cc_emails'] = cc_emails
    else:
        roll_kwargs['cc_on_failure_emails'] = 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 = api.roll_util.fake_author(
            next(iter(authors))
        )._asdict()

    change = api.auto_roller.attempt_roll(
        api.auto_roller.Options(
            remote=checkout.options.remote,
            upstream_ref=checkout.options.branch,
            dry_run=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,
            **roll_kwargs,
        ),
        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):  # pylint: disable=invalid-name
    """Create tests."""

    def properties(api, path, dry_run=True, equivalent_remotes=(), **kwargs):
        props = api.checkout.git_properties(
            remote='https://host.googlesource.com/manifest',
            equivalent_remotes=equivalent_remotes,
            match_branch=True,
        )
        props['forge_author'] = True
        props['path_to_update'] = path
        props['dry_run'] = dry_run
        props.update(**kwargs)
        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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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.status_check.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()
    )
