# Copyright (C) 2019, 2022 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import calendar
import datetime
import json
import os
import time
import twisted

from base64 import b64encode
from buildbot.process.results import SUCCESS, FAILURE, CANCELLED, WARNINGS, SKIPPED, EXCEPTION, RETRY
from buildbot.util import httpclientservice, service
from buildbot.www.hooks.github import GitHubEventHandler
from steps import GitHub
from twisted.internet import defer
from twisted.internet import reactor
from twisted.internet.defer import succeed
from twisted.python import log
from twisted.web.client import Agent
from twisted.web.http_headers import Headers
from twisted.web.iweb import IBodyProducer
from zope.interface import implementer

custom_suffix = '-uat' if os.getenv('BUILDBOT_UAT') else ''

@implementer(IBodyProducer)
class JSONProducer(object):
    """
    Perform JSON asynchronously as to not lock the buildbot main event loop
    """

    def __init__(self, data):
        try:
            self.body = json.dumps(data, default=self.json_serialize_datetime).encode('utf-8')
        except TypeError:
            self.body = ''
        self.length = len(self.body)

    def startProducing(self, consumer):
        if self.body:
            consumer.write(self.body)
        return succeed(None)

    def pauseProducing(self):
        pass

    def stopProducing(self):
        pass

    def json_serialize_datetime(self, obj):
        """
        Serializing buildbot dates into UNIX epoch timestamps.
        """
        if isinstance(obj, datetime.datetime):
            return int(calendar.timegm(obj.timetuple()))

        raise TypeError("Type %s not serializable" % type(obj))


class Events(service.BuildbotService):

    EVENT_SERVER_ENDPOINT = 'https://ews.webkit{}.org/results/'.format(custom_suffix).encode()
    MAX_GITHUB_DESCRIPTION = 140
    SHORT_STEPS = (
        'configure-build',
        'validate-change',
        'configuration',
        'clean-up-git-repo',
        'fetch-branch-references',
        'show-identifier',
        'update-working-directory',
        'apply-patch',
        'kill-old-processes',
        'set-build-summary',
    )

    def __init__(self, master_hostname, type_prefix='', name='Events'):
        """
        Initialize the Events Plugin. Sends data to event server on specific buildbot events.
        :param type_prefix: [optional] prefix we want to add to the 'type' field on the json we send
         to event server. (i.e. ews-build, where 'ews-' is the prefix.
        :return: Events Object
        """
        service.BuildbotService.__init__(self, name=name)

        if type_prefix and not type_prefix.endswith("-"):
            type_prefix += "-"
        self.type_prefix = type_prefix
        self.master_hostname = master_hostname

    def sendDataToEWS(self, data):
        if os.getenv('EWS_API_KEY', None):
            data['EWS_API_KEY'] = os.getenv('EWS_API_KEY')
        agent = Agent(reactor)
        body = JSONProducer(data)

        agent.request(b'POST', self.EVENT_SERVER_ENDPOINT, Headers({'Content-Type': ['application/json']}), body)

    def sendDataToGitHub(self, repository, sha, data, user=None):
        username, access_token = GitHub.credentials(user=user)

        data['description'] = data.get('description', '')
        if len(data['description']) > self.MAX_GITHUB_DESCRIPTION:
            data['description'] = '{}...'.format(data['description'][:self.MAX_GITHUB_DESCRIPTION - 3])

        auth_header = b64encode('{}:{}'.format(username, access_token).encode('utf-8')).decode('utf-8')

        agent = Agent(reactor)
        body = JSONProducer(data)
        d = agent.request(b'POST', GitHub.commit_status_url(sha, repository).encode('utf-8'), Headers({
            'Authorization': ['Basic {}'.format(auth_header)],
            'User-Agent': ['python-twisted/{}'.format(twisted.__version__)],
            'Accept': ['application/vnd.github.v3+json'],
            'Content-Type': ['application/json'],
        }), body)

    def getBuilderName(self, build):
        if not (build and 'properties' in build):
            return ''

        return build.get('properties').get('buildername')[0]

    def extractProperty(self, build, property_name):
        if not (build and 'properties' in build and property_name in build['properties']):
            return None

        return build.get('properties').get(property_name)[0]

    @defer.inlineCallbacks
    def buildStarted(self, key, build):
        if not build.get('properties'):
            build['properties'] = yield self.master.db.builds.getBuildProperties(build.get('buildid'))

        builder = yield self.master.db.builders.getBuilder(build.get('builderid'))
        builder_display_name = builder.get('description')

        data = {
            "type": self.type_prefix + "build",
            "status": "started",
            "hostname": self.master_hostname,
            "patch_id": self.extractProperty(build, 'patch_id'),
            "build_id": build.get('buildid'),
            "builder_id": build.get('builderid'),
            "number": build.get('number'),
            "result": build.get('results'),
            "started_at": build.get('started_at'),
            "complete_at": build.get('complete_at'),
            "state_string": build.get('state_string'),
            "builder_name": self.getBuilderName(build),
            "builder_display_name": builder_display_name,
        }

        self.sendDataToEWS(data)

    def buildFinishedGitHub(self, build):
        sha = self.extractProperty(build, 'github.head.sha')
        repository = self.extractProperty(build, 'repository')

        if not sha or not repository:
            print('Pull request number defined, but sha is {} and repository {}, which are invalid'.format(sha, repository))
            print('Not reporting build result to GitHub')
            return

        data_to_send = dict(
            owner=(self.extractProperty(build, 'owners') or [None])[0],
            repo=(self.extractProperty(build, 'github.head.repo.full_name') or '').split('/')[-1],
            sha=sha,
            target_url='{}#/builders/{}/builds/{}'.format(self.master.config.buildbotURL, build.get('builderid'), build.get('number')),
            state={
                SUCCESS: 'success',
                WARNINGS: 'success',
                SKIPPED: 'success',
                RETRY: 'pending',
                FAILURE: 'failure'
            }.get(build.get('results'), 'error'),
            description=build.get('state_string'),
            context=build['description'] + custom_suffix,
        )
        self.sendDataToGitHub(repository, sha, data_to_send, user=GitHub.user_for_queue(self.extractProperty(build, 'buildername')))

    @defer.inlineCallbacks
    def buildFinished(self, key, build):
        if not build.get('properties'):
            build['properties'] = yield self.master.db.builds.getBuildProperties(build.get('buildid'))
        if not build.get('steps'):
            build['steps'] = yield self.master.db.steps.getSteps(build.get('buildid'))

        builder = yield self.master.db.builders.getBuilder(build.get('builderid'))
        build['description'] = builder.get('description', '?')

        if self.extractProperty(build, 'github.number'):
            return self.buildFinishedGitHub(build)

        patch_id = self.extractProperty(build, 'patch_id')
        if not patch_id:
            return

        data = {
            "type": self.type_prefix + "build",
            "status": "finished",
            "hostname": self.master_hostname,
            "patch_id": self.extractProperty(build, 'patch_id'),
            "build_id": build.get('buildid'),
            "builder_id": build.get('builderid'),
            "number": build.get('number'),
            "result": build.get('results'),
            "started_at": build.get('started_at'),
            "complete_at": build.get('complete_at'),
            "state_string": build.get('state_string'),
            "builder_name": self.getBuilderName(build),
            "builder_display_name": builder.get('description'),
            "steps": build.get('steps'),
        }

        self.sendDataToEWS(data)

    @defer.inlineCallbacks
    def stepStartedGitHub(self, build, state_string):
        sha = self.extractProperty(build, 'github.head.sha')
        repository = self.extractProperty(build, 'repository')
        if not sha or not repository:
            print('Pull request number defined, but sha is {} and repository {}, which are invalid'.format(sha, repository))
            print('Not reporting step started to GitHub')
            return

        builder = yield self.master.db.builders.getBuilder(build.get('builderid'))

        data_to_send = dict(
            owner=(self.extractProperty(build, 'owners') or [None])[0],
            repo=(self.extractProperty(build, 'github.head.repo.full_name') or '').split('/')[-1],
            sha=sha,
            target_url='{}#/builders/{}/builds/{}'.format(self.master.config.buildbotURL, build.get('builderid'), build.get('number')),
            state={
                SUCCESS: 'pending',
                WARNINGS: 'pending',
                FAILURE: 'failure',
                EXCEPTION: 'error',
            }.get(build.get('results'), 'pending'),
            description=state_string,
            context=builder.get('description', '?') + custom_suffix,
        )
        self.sendDataToGitHub(repository, sha, data_to_send, user=GitHub.user_for_queue(self.extractProperty(build, 'buildername')))

    @defer.inlineCallbacks
    def stepStarted(self, key, step):
        state_string = step.get('state_string')
        if state_string == 'pending':
            state_string = 'Running {}'.format(step.get('name'))

        build = yield self.master.db.builds.getBuild(step.get('buildid'))
        if not build.get('properties'):
            build['properties'] = yield self.master.db.builds.getBuildProperties(step.get('buildid'))

        # We need to force the defered properties to resolve
        if build['properties'].get('github.number') and build.get('step') not in self.SHORT_STEPS:
            self.stepStartedGitHub(build, state_string)

        data = {
            "type": self.type_prefix + "step",
            "status": "started",
            "hostname": self.master_hostname,
            "step_id": step.get('stepid'),
            "build_id": step.get('buildid'),
            "result": step.get('results'),
            "state_string": state_string,
            "started_at": step.get('started_at'),
            "complete_at": step.get('complete_at'),
        }

        self.sendDataToEWS(data)

    def stepFinished(self, key, step):
        data = {
            "type": self.type_prefix + "step",
            "status": "finished",
            "hostname": self.master_hostname,
            "step_id": step.get('stepid'),
            "build_id": step.get('buildid'),
            "result": step.get('results'),
            "state_string": step.get('state_string'),
            "started_at": step.get('started_at'),
            "complete_at": step.get('complete_at'),
        }

        self.sendDataToEWS(data)

    @defer.inlineCallbacks
    def startService(self):
        yield service.BuildbotService.startService(self)

        startConsuming = self.master.mq.startConsuming

        self._buildStartedConsumer = yield startConsuming(self.buildStarted, ('builds', None, 'new'))
        self._buildCompleteConsumer = yield startConsuming(self.buildFinished, ('builds', None, 'finished'))
        self._stepStartedConsumer = yield startConsuming(self.stepStarted, ('steps', None, 'started'))
        self._stepFinishedConsumer = yield startConsuming(self.stepFinished, ('steps', None, 'finished'))

    def stopService(self):
        self._buildStartedConsumer.stopConsuming()
        self._buildCompleteConsumer.stopConsuming()
        self._stepStartedConsumer.stopConsuming()
        self._stepFinishedConsumer.stopConsuming()


class GitHubEventHandlerNoEdits(GitHubEventHandler):
    OPEN_STATES = ('open',)
    PUBLIC_REPOS = ('WebKit/WebKit',)
    SENSATIVE_FIELDS = ('github.title',)
    UNSAFE_MERGE_QUEUE_LABEL = 'unsafe-merge-queue'
    MERGE_QUEUE_LABEL = 'merge-queue'
    LABEL_PROCESS_DELAY = 10

    @classmethod
    def file_with_status_sign(cls, info):
        if info.get('status') in ('removed', 'renamed'):
            return '--- {}'.format(info['filename'])
        return '+++ {}'.format(info['filename'])

    def _get_commit_msg(self, repo, sha):
        return ''

    @defer.inlineCallbacks
    def _get_pr_files(self, repo, number):
        # Copied from https://github.com/buildbot/buildbot/blob/v2.10.5/master/buildbot/www/hooks/github.py to include added/modified/deleted
        headers = {"User-Agent": "Buildbot"}
        if self._token:
            headers["Authorization"] = "token " + self._token

        url = "/repos/{}/pulls/{}/files".format(repo, number)
        http = yield httpclientservice.HTTPClientService.getService(
            self.master,
            self.github_api_endpoint,
            headers=headers,
            debug=self.debug,
            verify=self.verify,
        )
        res = yield http.get(url)
        if 200 <= res.code < 300:
            data = yield res.json()
            return [self.file_with_status_sign(f) for f in data]

        log.msg('Failed fetching PR files: response code {}'.format(res.code))
        return []

    def extractProperties(self, payload):
        result = super(GitHubEventHandlerNoEdits, self).extractProperties(payload)
        if payload.get('base', {}).get('repo', {}).get('full_name') not in self.PUBLIC_REPOS:
            for field in self.SENSATIVE_FIELDS:
                if field in result:
                    del result[field]
        return result

    def handle_pull_request(self, payload, event):
        pr_number = payload['number']
        action = payload.get('action')
        state = payload.get('pull_request', {}).get('state')
        labels = [label.get('name') for label in payload.get('pull_request', {}).get('labels', [])]

        if state not in self.OPEN_STATES:
            log.msg("PR #{} is '{}', which triggers nothing".format(pr_number, state))
            return ([], 'git')

        if action == 'labeled' and self.UNSAFE_MERGE_QUEUE_LABEL in labels:
            log.msg("PR #{} was labeled for unsafe-merge-queue".format(pr_number))
            # 'labeled' is usually an ignored action, override it to force build
            payload['action'] = 'synchronize'
            time.sleep(self.LABEL_PROCESS_DELAY)
            return super(GitHubEventHandlerNoEdits, self).handle_pull_request(payload, 'unsafe_merge_queue')
        if action == 'labeled' and self.MERGE_QUEUE_LABEL in labels:
            log.msg("PR #{} was labeled for merge-queue".format(pr_number))
            # 'labeled' is usually an ignored action, override it to force build
            payload['action'] = 'synchronize'
            time.sleep(self.LABEL_PROCESS_DELAY)
            return super(GitHubEventHandlerNoEdits, self).handle_pull_request(payload, 'merge_queue')

        return super(GitHubEventHandlerNoEdits, self).handle_pull_request(payload, event)
