import json
import requests


def github_rest_api(
        *, endpoint=None, auth=None, headers=None, state=None, session=None
    ):
    """Do a GET from the GitHub V3 REST API.

    endpoint = the HTTP endpoint to call; if endpoint starts with / (for
               example, '/orgs/microsoft'), it will be appended to
               https://api.github.com
    auth     = optional authentication tuple - (username, pat)
               If not specified, values are read from username/PAT settings in
               local config.json file
    headers  = optional dictionary of HTTP headers to pass
    state    = optional state object, where settings such as the session object
               are stored. If provided, must have properties as used below.
    session  = optional Requests session object reference. If not provided,
               state.requests_session is the default session object. Use
               the session argument to override that default and use a
               different session. Use of a session object improves performance.

    Returns the response object.

    Sends the Accept header to use version V3 of the GitHub API. This can
    be explicitly overridden by passing a different Accept header if desired.
    """
    print(f"\rGitHub API called: {endpoint}", end="")

    if not endpoint:
        print("ERROR: github_api() called with no endpoint")
        return None

    # set auth to default if needed
    if not auth:
        settings = json.loads(open("config.json").read())  # read config file
        auth = (settings["username"], settings["PAT"])

    # add the V3 Accept header to the dictionary
    headers = {} if not headers else headers
    headers_dict = {**{"Accept": "application/vnd.github.v3+json"}, **headers}

    # make the API call
    if session:
        sess = session  # explictly passed Requests session
    elif state:
        if state.requests_session:
            sess = state.requests_session  # Requests session on the state objet
        else:
            sess = requests.session()  # create a new Requests session
            state.requests_session = sess  # save it in the state object
    else:
        # if no state or session specified, create a temporary Requests
        # session to use below. Note it's not saved/re-used in this scenario
        # so performance won't be optimized.
        sess = requests.session()

    sess.auth = auth
    full_endpoint = (
        "https://api.github.com" + endpoint if endpoint[0] == "/" else endpoint
    )
    response = sess.get(full_endpoint, headers=headers_dict)

    if state and state.verbose:
        print("    Endpoint: " + endpoint)

    if state:
        # update rate-limit settings
        try:
            state.last_ratelimit = int(response.headers["X-RateLimit-Limit"])
            state.last_remaining = int(response.headers["X-RateLimit-Remaining"])
        except KeyError:
            # This is the strange and rare case (which we've encountered) where
            # an API call that normally returns the rate-limit headers doesn't
            # return them. Since these values are only used for monitoring, we
            # use nonsensical values here that will show it happened, but won't
            # crash a long-running process.
            state.last_ratelimit = 999999
            state.last_remaining = 999999

        if state.verbose:
            # display rate-limite status
            username = auth[0] if auth else "(non-authenticated)"
            used = state.last_ratelimit - state.last_remaining
            print(
                "  Rate Limit: {0} available, {1} used, {2} total for {3}".format(
                    state.last_remaining, used, state.last_ratelimit, username
                )
            )

    return response