# -*- coding: utf-8 -*-

from http.server import BaseHTTPRequestHandler,HTTPServer
import json
import sys
import irc

# Attributes of the server this bot will run on
SERVER_HOST = 'server.url.or.ip'
SERVER_PORT = 11022

# Attributes of the IRC connection
IRC_SERVER = '127.0.0.1'
IRC_PORT = 6667
IRC_CHANNEL = ['#dev']
IRC_NICK = 'commits-notifier'

# Set the password for your registered empty, leave empty if not applicable
# Note: freenode(and potentially other servers) want password to be of the form
# "nick:pass", so for ex. IRC_PASS = 'WfTestBot:mypass123'
IRC_PASS = ''

# a dictionary of branches push-related events should be enabled for, or empty if all are enabled
GH_PUSH_ENABLED_BRANCHES = [] # for example, ['master', 'testing', 'author/repo:branch']

# a dictionary of branches push-related events should be ignored for, or empty if all are enabled
GH_PUSH_IGNORE_BRANCHES = ['gh-pages']

# a list of push-related events the bot should post notifications for
GH_PUSH_ENABLED_EVENTS = ['push'] # no others supported for now

# a list of PR-related events the bot should post notifications for
# notice 'merged' is just a special case of 'closed'
GH_PR_ENABLED_EVENTS = ['opened', 'closed', 'reopened'] # could also add 'synchronized', 'labeled', etc.

# handle POST events from github server
# We should also make sure to ignore requests from the IRC, which can clutter
# the output with errors
CONTENT_TYPE = 'content-type'
CONTENT_LEN = 'content-length'
EVENT_TYPE = 'x-github-event'

ircc = irc.IRC()
ircc.connect(IRC_SERVER, IRC_PORT, IRC_CHANNEL, IRC_NICK)

def handle_push_event(irc, data):
    if GH_PUSH_ENABLED_BRANCHES:
        branch = get_branch_name_from_push_event(data)
        repo = data['repository']['full_name']
        repobranch = repo + ':' + branch
        if not branch in GH_PUSH_ENABLED_BRANCHES:
            if not repobranch in GH_PUSH_ENABLED_BRANCHES:
                return
    
    if GH_PUSH_IGNORE_BRANCHES:
        branch = get_branch_name_from_push_event(data)
        if branch in GH_PUSH_IGNORE_BRANCHES:
            return

    if 'push' in GH_PUSH_ENABLED_EVENTS:
        handle_forward_push(irc, data)

def handle_pull_request(irc, data):
    author = data['sender']['login']
    if not data['action'] in GH_PR_ENABLED_EVENTS:
        return

    action = data['action']
    merged = data['pull_request']['merged']
    action = 'merged' if action == 'closed' and merged else action
    pr_num = '#' + str(data['number'])
    title = data['pull_request']['title']

    print("PR event:")
    print(f"@{author} {action} pull request {pr_num}: {title}")
    print("==============================================")

    irc.send("#dev", f"@{author} {action} pull request {pr_num}: {title}")

def get_branch_name_from_push_event(data):
    return data['ref'].split('/')[-1]

def handle_forward_push(irc, data):
    author = data['commits'][0]['author']['name']

    num_commits = len(data['commits'])
    num_commits = str(num_commits) + " commit" + ('s' if num_commits > 1 else '')

    branch = get_branch_name_from_push_event(data)

    commits = list(map(fmt_commit, data['commits']))
    for commit in commits:
        print("Push event:")
        print(f"@{author} pushed {num_commits} to {branch}: {commit}")
        print("==============================================")
        irc.send("#dev", f"@{author} pushed {num_commits} to {branch}: {commit}")

def fmt_commit(cmt):
    hsh = cmt['id'][:10]
    # author = cmt['author']['name']
    message = cmt['message'].split("\n")
    message = message[0] \
            + ('...' if len(message) > 1 else '')

    return '{}: {}'.format(hsh, message)

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        pass
    def do_CONNECT(self):
        pass
    def do_POST(self):
        if not all(x in self.headers for x in [CONTENT_TYPE, CONTENT_LEN, EVENT_TYPE]):
            return
        content_type = self.headers['content-type']
        content_len = int(self.headers['content-length'])
        event_type = self.headers['x-github-event']

        if content_type != "application/json":
            self.send_error(400, "Bad Request", "Expected a JSON request")
            return

        data = self.rfile.read(content_len)
        if sys.version_info < (3, 6):
            data = data.decode()

        self.send_response(200)
        self.send_header('content-type', 'text/html')
        self.end_headers()
        self.wfile.write(bytes('OK', 'utf-8'))

        if event_type == 'push':
            handle_push_event(ircc, json.loads(data))
        elif event_type == 'pull_request':
            handle_pull_request(ircc, json.loads(data))
        return

# Run Github webhook handling server
try:
    server = HTTPServer((SERVER_HOST, SERVER_PORT), MyHandler)
    server.serve_forever()
except KeyboardInterrupt:
    print("Exiting")
    server.socket.close()
