# -*- coding: utf-8 -*-
#  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
#
#    http://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.

import getpass
import base64
import urllib
import urllib.request
from datetime import datetime
import re

try:
    import json
except ImportError:
    import simplejson as json


def git_time(obj):
    if obj is None:
        return None
    return datetime.strptime(obj[0:19], "%Y-%m-%dT%H:%M:%S")


class GitPullRequest:
    """Pull Request from Git"""

    storm_jira_number = re.compile("STORM-[0-9]+", re.I)

    def __init__(self, data, parent):
        self.data = data
        self.parent = parent

    def html_url(self):
        return self.data["html_url"]

    def title(self):
        return self.data["title"]

    def trimmed_title(self):
        limit = 40
        title = self.data["title"]
        return title if len(title) < limit else title[0:limit] + "..."

    def number(self):
        return self.data["number"]

        # TODO def review_comments

    def user(self):
        return self.data["user"]["login"]

    def from_branch(self):
        return self.data["head"]["ref"]

    def from_repo(self):
        return self.data["head"]["repo"]["clone_url"]

    def merged(self):
        return self.data["merged_at"] is not None

    def raw(self):
        return self.data

    def created_at(self):
        return git_time(self.data["created_at"])

    def updated_at(self):
        return git_time(self.data["updated_at"])

    def merged_at(self):
        return git_time(self.data["merged_at"])

    def has_jira_id(self):
        return GitPullRequest.storm_jira_number.search(self.title())

    def jira_id(self):
        return GitPullRequest.storm_jira_number.search(self.title()).group(0).upper()

    def __str__(self):
        return self.html_url()

    def __repr__(self):
        return self.html_url()


class GitHub:
    """Github API"""

    def __init__(self, options):
        self.headers = {}
        if options.gituser:
            gitpassword = getpass.getpass("github.com user " + options.gituser + ":")
            authstr = base64.encodestring('%s:%s' % (options.gituser, gitpassword)).replace('\n', '')
            self.headers["Authorization"] = "Basic " + authstr

    def pulls(self, user, repo, type="all"):
        page = 1
        ret = []
        while True:
            url = f"https://api.github.com/repos/{user}/{repo}/pulls?state={type}&page={page}"
            req = urllib.request.Request(url, None, self.headers)
            result = urllib.request.urlopen(req)
            contents = result.read().decode()
            if result.getcode() != 200:
                raise Exception(result.getcode() + " != 200 " + contents)
            got = json.loads(contents)
            for part in got:
                ret.append(GitPullRequest(part, self))
            if len(got) == 0:
                return ret
            page = page + 1

    def open_pulls(self, user, repo):
        return self.pulls(user, repo, "open")

    def pull(self, user, repo, number):
        url = f"https://api.github.com/repos/{user}/{repo}/pulls/{number}"
        req = urllib.request.Request(url, None, self.headers)
        result = urllib.request.urlopen(req)
        contents = result.read().decode()
        if result.getcode() != 200:
            raise Exception(result.getcode() + " != 200 " + contents)
        got = json.loads(contents)
        return GitPullRequest(got, self)
