# Copyright 2021 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.
"""Utility functions common to multiple recipes that don't fit elsewhere."""

import json
import re

import attr
from google.protobuf import json_format
from recipe_engine import recipe_api


@attr.s
class ChangeWithComments:
    change = attr.ib()
    details = attr.ib()
    commit_message = attr.ib()
    comments = attr.ib()


class UtilApi(recipe_api.RecipeApi):
    def get_change_with_comments(self):
        input_ = self.m.buildbucket.build.input
        change = input_.gerrit_changes[0]
        change_id = str(change.change)
        details = self.m.gerrit.change_details(
            'change details',
            change_id=change_id,
            host=input_.gerrit_changes[0].host,
            query_params=['ALL_COMMITS', 'ALL_REVISIONS', 'ALL_FILES'],
            test_data=self.m.json.test_api.output(
                {
                    'owner': {'email': 'coder@example.com',},
                    'current_revision': 'a' * 40,
                    'revisions': {
                        'a'
                        * 40: {
                            'files': [],
                            'commit': {'message': '',},
                            'description': 'description',
                        }
                    },
                    'revert_of': 0,
                }
            ),
        ).json.output

        current_revision = details['revisions'][details['current_revision']]
        commit_message = current_revision['commit']['message']

        comments = []

        for revision in details['revisions'].values():
            if revision.get('description'):
                comments.append(revision['description'])

        comments_result = self.m.gerrit.list_change_comments(
            "list change comments",
            change_id,
            test_data=self.m.json.test_api.output(
                {'/PATCHSET_LEVEL': [{'message': ''}],}
            ),
        ).json.output

        for _, comment_data in comments_result.items():
            comments.extend(x['message'] for x in comment_data)

        return ChangeWithComments(change, details, commit_message, comments)

    def find_matching_comment(self, rx, comments):
        """Find a comment in comments that matches regex object rx."""
        result = None
        with self.m.step.nest('checking comments'):
            for i, comment in enumerate(comments):
                with self.m.step.nest('comment ({})'.format(i)) as pres:
                    pres.step_summary_text = comment
                    match = re.search(rx, comment)
                    if match:
                        pres.step_summary_text = 'MATCH: {}'.format(comment)
                        result = match
                        break

            if result:
                with self.m.step.nest('found'):
                    pass

        return result

    def build_metadata(self):
        return {
            'bb_id': self.m.buildbucket.build.id,
            'swarming_id': self.m.swarming.task_id,
            'builder': self.m.buildbucket_util.full_builder_name(),
            'url': self.m.buildbucket_util.build_url,
            'triggers': [
                json.loads(json_format.MessageToJson(x))
                for x in self.m.scheduler.triggers
            ],
        }
