import json
import bottle
from bottle import Jinja2Template, jinja2_view, static_file, response, Bottle, request
import traceback
import functools
import threading
import os
import base64
import requests
import logging, coloredlogs
from util import logsetup

LOGLEVEL = logging.INFO
FORMAT = "[%(asctime)s] [%(levelname)7s] %(name)7s: %(message)s"
logger = logsetup("spotify_refresher.log", FORMAT, LOGLEVEL)

app = Bottle()

with open('config.json') as f:
    config = json.load(f)

current_tokens = {'access': None, 'refresh': None}
current_timer = None

def get_access_token_and_register(code=None, grant_type='authorization_code'):
    global current_tokens
    global current_timer

    logger.info(f"Refreshing access/refresh token (grant type: {grant_type})...")

    if current_timer:
        logger.debug("There is a current timer, cancelling it...")
        current_timer.cancel()

    if grant_type == 'refresh_token':
        token_params = {'grant_type': grant_type, 'refresh_token': current_tokens['refresh']}
    else:
        token_params = {'grant_type': grant_type,
                        'code': code,
                        'redirect_uri': 'https://spotify.segfault.party/callback'}

    resp = requests.post('https://accounts.spotify.com/api/token', data=token_params,
                         auth=(config['client_id'], config['client_secret']))

    data = resp.json()

    try:
        current_tokens['access'] = data['access_token']

        if 'refresh_token' in data:
            current_tokens['refresh'] = data['refresh_token']

        expires_in = data['expires_in']
        current_timer = threading.Timer(expires_in, get_access_token_and_register, args=None,
                kwargs={'code': current_tokens['refresh'], 'grant_type': 'refresh_token'})
        current_timer.start()
    except:
        logger.error("Error while trying to refresh token!", exc_info=True)
        logger.info(f"Data returned from the API: {data}")
        return False

    logger.info("Successfully refreshed token!")

    return True

@app.route('/callback')
def register_access_token():
    if 'code' in request.query:
        # Success!
        if get_access_token_and_register(request.query.code):
            return "You can press enter now."
    return "Something went wrong, or you didn't allow the access :<"

@app.route('/get_token')
def get_token():
    logger.info("Access token requested.")
    return current_tokens['access']

app.run(server='auto', host='127.0.0.1', port=9009)
