# Path: helpers/google_api.py
# class GoogleAPIException(Exception):
# def oauth2_flow(**kwargs):
# def http_from_oauth2(auth_json):
# def user_info(auth_json):
# def drive_service():
# def list_drive_files(auth_json, query="", page_token=None):
# def get_worksheets(auth_json, spreadsheet_key):
# def get_cell_data(auth_json, spreadsheet_key, worksheet_key, limit=None):
# def create_spreadsheet(auth_json, title=""):
# def create_worksheet(auth_json, spreadsheet_key):
# def save_data(auth_json, spreadsheet_key, worksheet_key, data=[[]]):
# def _key(heading):
# def _val(val):    #::::....|...                       ___(_)
# 
# Path: helpers/sessions.py
# class SessionHandler(RequestHandler):
# 
#     # Override dispatch method to get and save session data with every request
#     def dispatch(self):
#         self.session_store = get_store(request=self.request)
#         try:
#             RequestHandler.dispatch(self)
#         finally:
#             self.session_store.save_sessions(self.response)
# 
#     # Make session data available within handlers
#     @cached_property
#     def session(self):
#         return self.session_store.get_session()
# 
#     def current_user(self, user=None):
#         if user:
#             self.session['current_user'] = user.google_id
# 
#         if 'current_user' in self.session:
#             return User.get_by_google_id(self.session['current_user'])
#         else:
#             return None
# 
# Path: helpers/views.py
# def render(template_file, template_data={}, ):
#     template = APP_RENDER.get_template(template_file)
#     template_data['VERSION'] = main.__version__
#     return template.render(template_data)
# 
# Path: helpers/slug.py
# class SlugError(Exception):
#     def __init__(self, value):
#     def __str__(self):
# def create(string):
# def validate(string):
# 
# Path: controllers/root.py
# def error_500(request, response, exception):
#     msg_info = (request.method, request.path_url, request.POST.items(), exception, exception.__class__)
#     logging.error("%s %s %s 500 '%s' %s" % msg_info)
#     response.write(render('500.html'))
#     response.set_status(500)
# 
# Path: models/user.py
# class User(db.Model):
# 
#     created_at          = db.DateTimeProperty(required=True)
#     credentials         = db.TextProperty(default=u'')
#     google_birthday     = db.StringProperty(default=u'')
#     google_email        = db.EmailProperty()
#     google_gender       = db.StringProperty(default=u'')
#     google_id           = db.StringProperty(required=True)
#     google_locale       = db.StringProperty(default=u'')
#     google_name         = db.StringProperty(default=u'')
#     google_picture_url  = db.StringProperty(default=u'')
#     last_login_at       = db.DateTimeProperty(required=True)
#     modified_at         = db.DateTimeProperty(required=True)
#     profile_description = db.TextProperty(default=u'')
#     profile_email       = db.TextProperty(default=u'')
#     profile_name        = db.StringProperty(default=u'')
#     profile_slug        = db.StringProperty(required=True)
#     profile_web_address = db.TextProperty(default=u'')
# 
#     def refresh_token(self):
#         if self.credentials:
#             return json.loads(self.credentials).get('refresh_token')
#         else:
#             None
# 
#     def fetch_data_sources(self):
#         return self.data_sources.order('-modified_at').fetch(limit=None)
# 
#     def to_dict(self):
#         return {
#             'created_at':          self.created_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'credentials':         self.credentials,
#             'data_sources':        [ds.to_dict() for ds in self.fetch_data_sources()],
#             'google_birthday':     self.google_birthday,
#             'google_email':        self.google_email,
#             'google_gender':       self.google_gender,
#             'google_id':           self.google_id,
#             'google_locale':       self.google_locale,
#             'google_name':         self.google_name,
#             'google_picture_url':  self.google_picture_url,
#             'last_login_at':       self.last_login_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'modified_at':         self.modified_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'profile_description': self.profile_description,
#             'profile_email':       self.profile_email,
#             'profile_name':        self.profile_name,
#             'profile_slug':        self.profile_slug,
#             'profile_web_address': self.profile_web_address
#             }
# 
#     @classmethod
#     def get_by_slug(self, profile_slug):
#         """ Find a user with the specified profile slug """
#         return User.gql("WHERE profile_slug = :1", profile_slug).get()
# 
#     @classmethod
#     def get_by_google_id(self, google_id):
#         """ Find a user with the specified google id """
#         return User.gql("WHERE google_id = :1", google_id).get()


import logging
import random
from datetime import datetime
from helpers import google_api
from helpers.sessions import SessionHandler
from helpers.views import render
from helpers import slug
from controllers.root import error_500
from models.user import User


# Clear user session and return to home page
class LogoutRoute(SessionHandler):
    def get(self):
        if 'current_user' in self.session:
            del self.session['current_user']
        self.redirect('/')


# Handle oAuth2 callback
# Create session and (if required) user account
class OAuth2CallbackRoute(SessionHandler):
    def get(self):
        
        code = self.request.GET.get('code')

        logging.debug("Auth Code: %s" % code)
        logging.debug("Session (at start): %s" % self.session)

        if None == code:
            # TODO Display cancelled login page issue#27
            return self.response.write('No authentication code returned')

        try:
            flow = google_api.oauth2_flow()
            auth = flow.step2_exchange(code)
            now  = datetime.now()

            # Get Google user info

# Path: helpers/google_api.py
# class GoogleAPIException(Exception):
# def oauth2_flow(**kwargs):
# def http_from_oauth2(auth_json):
# def user_info(auth_json):
# def drive_service():
# def list_drive_files(auth_json, query="", page_token=None):
# def get_worksheets(auth_json, spreadsheet_key):
# def get_cell_data(auth_json, spreadsheet_key, worksheet_key, limit=None):
# def create_spreadsheet(auth_json, title=""):
# def create_worksheet(auth_json, spreadsheet_key):
# def save_data(auth_json, spreadsheet_key, worksheet_key, data=[[]]):
# def _key(heading):
# def _val(val):    #::::....|...                       ___(_)
# 
# Path: helpers/sessions.py
# class SessionHandler(RequestHandler):
# 
#     # Override dispatch method to get and save session data with every request
#     def dispatch(self):
#         self.session_store = get_store(request=self.request)
#         try:
#             RequestHandler.dispatch(self)
#         finally:
#             self.session_store.save_sessions(self.response)
# 
#     # Make session data available within handlers
#     @cached_property
#     def session(self):
#         return self.session_store.get_session()
# 
#     def current_user(self, user=None):
#         if user:
#             self.session['current_user'] = user.google_id
# 
#         if 'current_user' in self.session:
#             return User.get_by_google_id(self.session['current_user'])
#         else:
#             return None
# 
# Path: helpers/views.py
# def render(template_file, template_data={}, ):
#     template = APP_RENDER.get_template(template_file)
#     template_data['VERSION'] = main.__version__
#     return template.render(template_data)
# 
# Path: helpers/slug.py
# class SlugError(Exception):
#     def __init__(self, value):
#     def __str__(self):
# def create(string):
# def validate(string):
# 
# Path: controllers/root.py
# def error_500(request, response, exception):
#     msg_info = (request.method, request.path_url, request.POST.items(), exception, exception.__class__)
#     logging.error("%s %s %s 500 '%s' %s" % msg_info)
#     response.write(render('500.html'))
#     response.set_status(500)
# 
# Path: models/user.py
# class User(db.Model):
# 
#     created_at          = db.DateTimeProperty(required=True)
#     credentials         = db.TextProperty(default=u'')
#     google_birthday     = db.StringProperty(default=u'')
#     google_email        = db.EmailProperty()
#     google_gender       = db.StringProperty(default=u'')
#     google_id           = db.StringProperty(required=True)
#     google_locale       = db.StringProperty(default=u'')
#     google_name         = db.StringProperty(default=u'')
#     google_picture_url  = db.StringProperty(default=u'')
#     last_login_at       = db.DateTimeProperty(required=True)
#     modified_at         = db.DateTimeProperty(required=True)
#     profile_description = db.TextProperty(default=u'')
#     profile_email       = db.TextProperty(default=u'')
#     profile_name        = db.StringProperty(default=u'')
#     profile_slug        = db.StringProperty(required=True)
#     profile_web_address = db.TextProperty(default=u'')
# 
#     def refresh_token(self):
#         if self.credentials:
#             return json.loads(self.credentials).get('refresh_token')
#         else:
#             None
# 
#     def fetch_data_sources(self):
#         return self.data_sources.order('-modified_at').fetch(limit=None)
# 
#     def to_dict(self):
#         return {
#             'created_at':          self.created_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'credentials':         self.credentials,
#             'data_sources':        [ds.to_dict() for ds in self.fetch_data_sources()],
#             'google_birthday':     self.google_birthday,
#             'google_email':        self.google_email,
#             'google_gender':       self.google_gender,
#             'google_id':           self.google_id,
#             'google_locale':       self.google_locale,
#             'google_name':         self.google_name,
#             'google_picture_url':  self.google_picture_url,
#             'last_login_at':       self.last_login_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'modified_at':         self.modified_at.strftime('%Y-%m-%d %H:%M:%s'),
#             'profile_description': self.profile_description,
#             'profile_email':       self.profile_email,
#             'profile_name':        self.profile_name,
#             'profile_slug':        self.profile_slug,
#             'profile_web_address': self.profile_web_address
#             }
# 
#     @classmethod
#     def get_by_slug(self, profile_slug):
#         """ Find a user with the specified profile slug """
#         return User.gql("WHERE profile_slug = :1", profile_slug).get()
# 
#     @classmethod
#     def get_by_google_id(self, google_id):
#         """ Find a user with the specified google id """
#         return User.gql("WHERE google_id = :1", google_id).get()


# Path: controllers/session.py
import logging
import random
from datetime import datetime
from helpers import google_api
from helpers.sessions import SessionHandler
from helpers.views import render
from helpers import slug
from controllers.root import error_500
from models.user import User



# Clear user session and return to home page
class LogoutRoute(SessionHandler):
    def get(self):
        if 'current_user' in self.session:
            del self.session['current_user']
        self.redirect('/')


# Handle oAuth2 callback
# Create session and (if required) user account
class OAuth2CallbackRoute(SessionHandler):
    def get(self):
        
        code = self.request.GET.get('code')

        logging.debug("Auth Code: %s" % code)
        logging.debug("Session (at start): %s" % self.session)

        if None == code:
            # TODO Display cancelled login page issue#27
            return self.response.write('No authentication code returned')

        try:
            flow = google_api.oauth2_flow()
            auth = flow.step2_exchange(code)
            now  = datetime.now()

            # Get Google user info

            google_user = google_api.user_info(auth.to_json())