# 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.
"""Find dependencies on pending CLs."""

import re
import urlparse

import attr
from recipe_engine import recipe_api


@attr.s
class Change(object):
    """Details of a matching change.

    This is meant to match the GerritChange message defined at
    https://source.chromium.org/chromium/infra/infra/+/master:go/src/go.chromium.org/luci/buildbucket/proto/common.proto;l=135?q=GerritChange
    A few fields have been added for use by this module.
    """

    gerrit_name = attr.ib(type=str)
    change = attr.ib(converter=int)
    project = attr.ib(type=str, default=None)
    patchset = attr.ib(type=int, default=None)
    status = attr.ib(type=str, default=None)
    commit = attr.ib(type=str, default=None)
    parents = attr.ib(type=list, default=attr.Factory(list))

    @property
    def host(self):
        return '{}-review.googlesource.com'.format(self.gerrit_name)

    @property
    def link(self):
        return 'https://{}/{}'.format(self.host, self.change)

    @property
    def name(self):
        return '{}:{}'.format(self.gerrit_name, self.change)

    def __str__(self):
        return self.name


class CqDepsApi(recipe_api.RecipeApi):
    """Find dependencies on pending CLs."""

    def __init__(self, *args, **kwargs):
        super(CqDepsApi, self).__init__(*args, **kwargs)
        self._details = {}

    def _lookup_cl(self, gerrit_name, commit):
        query_results = self.m.gerrit.change_query(
            'number {}'.format(commit),
            'commit:{}'.format(commit),
            host='{}-review.googlesource.com'.format(gerrit_name),
            # The strange value for _number is to ensure different hashes result
            # in different CL numbers by default. This way we don't accidentally
            # create a cycle by specifying a fixed default value.
            test_data=self.m.json.test_api.output(
                [{'_number': sum(ord(x) for x in commit),}]
            ),
        ).json.output
        return query_results[0]

    def resolve(self, gerrit_name, number, statuses=('NEW',)):
        """Recursively resolve dependencies of a CL.

        Resolve dependencies of a CL by parsing its commit message. Looks for
        lines like below, and only in the last "paragraph".

        Requires: gerritname:1, commas-supported:2
        Requires: name:4,spaces-not-required:3
        Requires: name:5,,,,extra-commas-ignored:6,,,,

        Args:
            gerrit_name (str): Name of Gerrit host of initial change.
            number (int|str): Gerrit number or git commit hash of initial
                change.
            statuses (seq(str)): CL statuses to accept.

        Returns a tuple of resolved Change objects (excluding the given change)
        and unresolved Change objects (which are not completely populated).
        This includes dependencies of parent changes with 'NEW' status but not
        the parent changes themselves.
        """

        with self.m.step.nest('resolve CL deps', status='last') as pres:
            with self.m.context(infra_steps=True):
                if isinstance(number, str):
                    number = self._lookup_cl(gerrit_name, number)['_number']

                seen = set()
                deps = {}
                parents = []
                unresolved = []
                initial_change = Change(gerrit_name, number)
                to_process = [initial_change] + initial_change.parents
                # Want all initial details calls to come from this step level so
                # their step names are predictable. Further calls can be made
                # anywhere and will hit the cache.
                _ = self._change_details(initial_change)

                while to_process:
                    current = to_process.pop()
                    deps[current.name] = current
                    seen.add(current.name)

                    parents.extend(current.parents)
                    to_process.extend(
                        x for x in current.parents if x.name not in seen
                    )

                    with self.m.step.nest('parents {}'.format(current.name)
                                          ) as pres:
                        if current.parents:
                            pres.step_summary_text = ', '.join(
                                x.name for x in current.parents
                            )
                        else:
                            pres.step_summary_text = (
                                'all parents already submitted'
                            )

                    for dep in self._resolve(current):
                        if dep.name not in deps:
                            details = self._change_details(dep)
                            if not details:
                                unresolved.append(dep)
                                continue
                            if details['status'] not in statuses:
                                continue

                            if dep.name not in seen:
                                to_process.append(dep)
                            deps[dep.name] = dep

                # If any dependency is a parent of another dependency remove the
                # parent since it's already being accounted for by patching in
                # its child.
                for parent in parents:
                    if parent.name in deps:
                        del deps[parent.name]

                del deps[initial_change.name]

                for dep in deps.itervalues():
                    pres.links[dep.name] = dep.link

                # Make sure the last step passes because _change_details might
                # fail for an individual CL in ways we don't care about.
                with self.m.step.nest('pass'):
                    pass

                return deps.values(), unresolved

    def _parse_commit_message(self, change):
        """Convert a commit message into a dependency list.

        For example,

            Requires: gerritname:1, commas-supported:2
            Requires: name:4,spaces-not-required:3
            Requires: 5,,,,extra-commas-ignored:6,,,,

        becomes

            [
                Change("gerritname", 1),
                Change("commas-supported", 2),
                Change("spaces-not-required", 3),
                Change("name", 4),
                Change(change.gerrit_name, 5),
                Change("extra-commas-ignored", 6),
            ]
        """

        details = self._change_details(change)
        current_revision = details['revisions'][details['current_revision']]
        commit_message = current_revision['commit']['message']
        last_paragraph = commit_message.split('\n\n')[-1]

        for line in last_paragraph.split('\n'):
            if ':' not in line:
                continue
            name, value = line.split(':', 1)

            if name != 'Requires':
                continue

            values = value.split(',')
            for val in values:
                val = val.strip()
                if not val:
                    continue
                try:
                    gerrit_name, number = val.split(':', 1)
                    yield Change(gerrit_name, number)
                except ValueError:
                    yield Change(change.gerrit_name, val)

    def _resolve(self, change):
        """Resolve dependencies of the given change.

        Retrieve and parse the commit message of the given change, extracting
        from "Requires:" lines (see resolve function above for details). Does
        not attempt to verify if these dependent changes are accessible or
        even valid.

        Args:
            change (Change): Change to resolve dependencies for.

        Returns a list of changes on which the given change depends. This
        includes dependencies of parent changes with 'NEW' status but not the
        parent changes themselves.
        """

        with self.m.step.nest('resolve deps for {}'.format(change)) as pres:
            deps = []
            for dep in self._parse_commit_message(change):
                deps.append(dep)
                pres.links[dep.name] = dep.link
            if not deps:
                pres.step_summary_text = 'no dependencies'
            return deps

    def _change_details(self, change, _kw_only=(), test_status='NEW'):
        assert not _kw_only
        if change.name in self._details:
            return self._details[change.name]

        try:
            step = self.m.gerrit.change_details(
                'details {}'.format(change),
                change_id=str(change.change),
                host=change.host,
                query_params=['CURRENT_COMMIT', 'CURRENT_REVISION',],
                max_attempts=5,
                test_data=self.m.json.test_api.output(
                    {
                        'current_revision': 'HASH',
                        'revisions': {
                            'HASH': {
                                '_number': 1,
                                'commit': {
                                    'message': '',
                                    'parents': [{'commit': 'PARENT',}],
                                },
                            }
                        },
                        'project': 'project',
                        'status': test_status,
                    }
                ),
            )
            details = step.json.output

        except self.m.step.StepFailure:
            details = {}

        self._details[change.name] = details
        if details:
            change.project = details['project']
            current_revision = details['revisions'][details['current_revision']]
            change.patchset = current_revision['_number']
            change.status = details['status']
            change.commit = details['current_revision']

            # If this CL is unsubmitted grab its parent and put it in the
            # cache. We could have several submitted parents in self._details,
            # but that's ok.
            if details['status'] == 'NEW':
                for parent in current_revision['commit']['parents']:
                    parent_change = Change(
                        gerrit_name=change.gerrit_name,
                        change=self._lookup_cl(
                            change.gerrit_name, parent['commit'],
                        )['_number'],
                    )
                    self._change_details(parent_change, test_status='SUBMITTED')
                    if parent_change.status == 'NEW':
                        if parent_change.commit != parent['commit']:
                            raise self.m.step.StepFailure(
                                '{} has parent {} which is not the current '
                                'revision of its parent, {} ({})'.format(
                                    change.name,
                                    parent['commit'],
                                    parent_change.name,
                                    parent_change.commit,
                                )
                            )

                        change.parents.append(parent_change)

        return self._details[change.name]
