# 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)
    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)]

    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 = api.roll_util.fake_author(
            next(iter(authors))
        )._asdict()

    change = api.auto_roller.attempt_roll(
        props.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):  # pylint: disable=invalid-name
    """Create tests."""

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

    def properties(api, path, dry_run=True, equivalent_remotes=(), **kwargs):
        props = api.checkout.git_properties(
            remote=manifest,
            equivalent_remotes=equivalent_remotes,
            match_branch=True,
        )
        props['forge_author'] = True
        props['path_to_update'] = path
        props['auto_roller_options'] = {'dry_run': dry_run, 'remote': manifest}

        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()
    )
