# 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(f'comment ({i})') as pres:
                    pres.step_summary_text = comment
                    match = re.search(rx, comment)
                    if match:
                        pres.step_summary_text = f'MATCH: {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
            ],
        }
