#!/usr/bin/env python
import cherrypy
import sys
import threading
import traceback
import webbrowser

import fitbit
from hbconfig import Config
from oauthlib.oauth2.rfc6749.errors import MismatchingStateError, MissingTokenError

from kino.slack.slackbot import SlackerAdapter
from kino.utils.data_handler import DataHandler


class Fitbit:

    def __init__(self, slackbot=None):
        self.data_handelr = DataHandler()

        if slackbot is None:
            self.slackbot = SlackerAdapter(
                channel=Config.slack.channel.get("REPORT", "#general")
            )
        else:
            self.slackbot = slackbot

    def _authorize(self):
        auth_server = OAuth2Server(
            Config.open_api.fitbit.client_id,
            Config.open_api.fitbit.client_secret)
        auth_server.browser_authorize()

        self.api = auth_server.fitbit

    def get_sleep_summary(self):
        self._authorize()
        sleep_data = self.api.sleep()

        summary_data = sleep_data["summary"]
        for data in sleep_data["sleep"]:
            if data["isMainSleep"]:
                summary_data["go_to_bed"] = data["startTime"]
                summary_data["wake_up"] = data["endTime"]
        return summary_data


class OAuth2Server:
    def __init__(self, client_id, client_secret,
                 redirect_uri='http://127.0.0.1:8080/'):
        """ Initialize the FitbitOauth2Client """
        self.success_html = """
            <h1>You are now authorized to access the Fitbit API!</h1>
            <br/><h3>You can close this window</h3>"""
        self.failure_html = """
            <h1>ERROR: %s</h1><br/><h3>You can close this window</h3>%s"""

        self.fitbit = fitbit.api.Fitbit(
            client_id,
            client_secret,
            redirect_uri=redirect_uri,
            timeout=10,
        )

    def browser_authorize(self):
        """
        Open a browser to the authorization url and spool up a CherryPy
        server to accept the response
        """
        url, _ = self.fitbit.client.authorize_token_url()
        # Open the web browser in a new thread for command-line browser support
        threading.Timer(1, webbrowser.open, args=(url,)).start()
        cherrypy.quickstart(self)

    @cherrypy.expose
    def index(self, state, code=None, error=None):
        """
        Receive a Fitbit response containing a verification code. Use the code
        to fetch the access_token.
        """
        error = None
        if code:
            try:
                self.fitbit.client.fetch_access_token(code)
            except MissingTokenError:
                error = self._fmt_failure(
                    'Missing access token parameter.</br>Please check that '
                    'you are using the correct client_secret')
            except MismatchingStateError:
                error = self._fmt_failure('CSRF Warning! Mismatching state')
        else:
            error = self._fmt_failure('Unknown error while authenticating')
        # Use a thread to shutdown cherrypy so we can return HTML first
        self._shutdown_cherrypy()
        return error if error else self.success_html

    def _fmt_failure(self, message):
        tb = traceback.format_tb(sys.exc_info()[2])
        tb_html = '<pre>%s</pre>' % ('\n'.join(tb)) if tb else ''
        return self.failure_html % (message, tb_html)

    def _shutdown_cherrypy(self):
        """ Shutdown cherrypy in one second, if it's running """
        if cherrypy.engine.state == cherrypy.engine.states.STARTED:
            threading.Timer(1, cherrypy.engine.exit).start()

@@ -723,25 +723,25 @@
 .fitbit.
-client_id
+CLIENT_ID
 ,%0A      
@@ -769,29 +769,29 @@
 .fitbit.
-client_secret
+CLIENT_SECRET
 )%0A      

use capital for config variables