import hmac
import json
import urllib.parse
from .main import PullReqState, parse_commands, db_query, INTERRUPTED_BY_HOMU_RE, synchronize
from . import utils
from .utils import lazy_debug
import github3
import jinja2
import requests
import pkg_resources
from bottle import get, post, run, request, redirect, abort, response
import hashlib
from threading import Thread
import sys
import os
import traceback

import bottle
bottle.BaseRequest.MEMFILE_MAX = 1024 * 1024 * 10


class G:
    pass
g = G()


def find_state(sha):
    for repo_label, repo_states in g.states.items():
        for state in repo_states.values():
            if state.merge_sha == sha:
                return state, repo_label

    raise ValueError('Invalid SHA')


def get_repo(repo_label, repo_cfg):
    repo = g.repos[repo_label]
    if not repo:
        g.repos[repo_label] = repo = g.gh.repository(repo_cfg['owner'], repo_cfg['name'])

        assert repo.owner.login == repo_cfg['owner']
        assert repo.name == repo_cfg['name']
    return repo


@get('/')
def index():
    return g.tpls['index'].render(repos=sorted(g.repos))


@get('/queue/<repo_label:path>')
def queue(repo_label):
    logger = g.logger.getChild('queue')

    lazy_debug(logger, lambda: 'repo_label: {}'.format(repo_label))

    if repo_label == 'all':
        labels = g.repos.keys()
        multiple = True
        repo_url = None
    else:
        labels = repo_label.split('+')
        multiple = len(labels) > 1
        repo_url = 'https://github.com/{}/{}'.format(
            g.cfg['repo'][repo_label]['owner'],
            g.cfg['repo'][repo_label]['name'])

    states = []
    for label in labels:
        try:
            states += g.states[label].values()
        except KeyError:
            abort(404, 'No such repository: {}'.format(label))

    pull_states = sorted(states)

    rows = []
    for state in pull_states:
        rows.append({
            'status': state.get_status(),
            'status_ext': ' (try)' if state.try_ else '',
            'priority': 'rollup' if state.rollup else state.priority,
            'url': 'https://github.com/{}/{}/pull/{}'.format(state.owner, state.name, state.num),
            'num': state.num,
            'approved_by': state.approved_by,
            'title': state.title,
            'head_ref': state.head_ref,
            'mergeable': 'yes' if state.mergeable is True else 'no' if state.mergeable is False else '',
            'assignee': state.assignee,
            'repo_label': state.repo_label,
            'repo_url': 'https://github.com/{}/{}'.format(state.owner, state.name),
        })

    return g.tpls['queue'].render(
        repo_url=repo_url,
        repo_label=repo_label,
        states=rows,
        oauth_client_id=g.cfg['github']['app_client_id'],
        total=len(pull_states),
        approved=len([x for x in pull_states if x.approved_by]),
        rolled_up=len([x for x in pull_states if x.rollup]),
        failed=len([x for x in pull_states if x.status == 'failure' or x.status == 'error']),
        multiple=multiple,
    )


@get('/callback')
def callback():
    logger = g.logger.getChild('callback')

    response.content_type = 'text/plain'

    code = request.query.code