#!env /usr/bin/env python3
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

""" GitHub utility library """
import re
import requests
from json import loads
import time

repo_pattern = re.compile('.*[:/]([^/]+)/([^/]+).git')
issues_api = "https://api.github.com/repos/%s/%s/issues"
traffic_api = "https://api.github.com/repos/%s/%s/traffic"
popular_api = "https://api.github.com/repos/%s/%s/popular"
rate_limit_api = "https://api.github.com/rate_limit"

def get_limited(url, params = None, auth = None):
    """ Get a GitHub API response, keeping in mind that we may
        be rate-limited by the abuse system """
    number_of_retries = 0
    resp = requests.get(url, params = params, auth=auth)
    while resp.status_code == 403 and number_of_retries < 20:
        js = resp.json()
        # If abuse-detection kicks in, sleep it off
        if 'You have triggered an abuse' in js['message']:
            time.sleep(5)
            number_of_retries += 1
            resp = requests.get(url, params = params, auth=auth)
        else:
            break
    resp.raise_for_status()
    return resp.json()

def get_tokens_left(auth = None):
    """ Gets number of GitHub tokens left this hour... """
    js = get_limited(rate_limit_api, auth=auth)
    tokens_left = js['rate']['remaining']
    return tokens_left


def issues(source, params={}, auth=None):
    local_params = {'per_page': 100, 'page': 1}
    local_params.update(params)

    repo_user = repo_pattern.findall(source['sourceURL'])[0]
    return get_limited(issues_api % repo_user, params=local_params, auth=auth)

def views(source, auth=None):
    repo_user = repo_pattern.findall(source['sourceURL'])[0]
    return get_limited("%s/views" % (traffic_api % repo_user), auth=auth)

def clones(source, auth=None):
    repo_user = repo_pattern.findall(source['sourceURL'])[0]
    return get_limited("%s/clones" % (traffic_api % repo_user), auth=auth)

def referrers(source, auth=None):
    repo_user = repo_pattern.findall(source['sourceURL'])[0]
    return get_limited("%s/referrers" % (popular_api % repo_user), auth=auth)
    
def user(user_url, auth=None):
    return get_limited(user_url, auth=auth)

def get_all(source, f, params={}, auth=None):
    acc = []
    page = params.get('page', 1)

    while True:
        time.sleep(1.5)
        items = f(source, params=params, auth=auth)
        if not items:
            break

        acc.extend(items)

        page = page + 1
        params.update({"page": page})

    return acc
