import sys
import datetime
from google.appengine.ext.webapp import Request
from google.appengine.ext.webapp import Response
from traceback import format_exception
from google.appengine.runtime import DeadlineExceededError

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import logging
from orangescape.config.routing import make_map
from orangescape.gateway.wsgi import BaseWSGIApplication
from orangescape.gateway.GAEWsgiUtil import getSession
from orangescape.model.server.PerfMonitor import PerfMonitor, saveDebugData
map = make_map()

class WSGIApplication(BaseWSGIApplication):
    """Wraps a set of webapp RequestHandlers in a WSGI-compatible application.
    This is based on webapp's WSGIApplication by Google, but uses Routes library
    (http://routes.groovie.org/) to match url's.
    """
    def __init__(self, mapper, debug = True):
        """Initializes this application with the given URL mapping.
        Args:
          mapper: a routes.mapper.Mapper instance
          debug: if true, we send Python stack traces to the browser on errors
        """
        self.mapper = mapper
        self.__debug = debug

    def isAdminAccess(self, request, session):
        accessKeyName = 'AccessKey'
        accessKey = request.get(accessKeyName)
        id = request.get('userid')
        if accessKey and id:
            logging.info('Checking admin access')
            metadata = session.getApplication().getSheetMetadata('User')
            logging.info('AccessKey given %s'%(accessKey))
            if metadata.getPublicCellMetadataDict().has_key(accessKeyName):
                accessKeyCell = metadata.getPublicCellMetadata(accessKeyName)
                logging.info('AccessKey cell exists in model %s. Checking instance %s'%(metadata.getSheetName(), id))
                instance = session.getIfExists(id, metadata)
                if instance and instance.getValue(accessKeyName)==accessKey:
                    logging.info('AccessKey in instance %s'%(instance.getValue(accessKeyName)))
                    return id
        return False

    def __call__(self, environ, start_response):
        """Called by WSGI when a request comes in."""
#        st = datetime.datetime.now()
        request = Request(environ)
        response = Response()
        WSGIApplication.active_instance = self

        #initialize the command factory here
        session = getSession()
        controller,action,kargs = self.initializeCommandFactory(request, response, environ, session, request.path)
        from appconfig import DEBUGGER_ENABLED
        if DEBUGGER_ENABLED is not None:
            pm = PerfMonitor(method='Main',session=session)
            pm.start()
        if controller and action:
            #do authentication
            isAuthenticated = False
            if 'section' in kargs:
                if kargs['section'] == 'open':
                    isAuthenticated = True
                if kargs['section'] == 'admin' and self.isAdminAccess(request, session):
                    isAuthenticated = True
                    controller.setUserId('guest')
                del kargs['section']
            if not isAuthenticated:
                #perform authentication
                from orangescape.model.server.util.AuthUtil import authenticate
                userid = authenticate(controller)
                if userid:
                    isAuthenticated = True
                    controller.setUserId(userid)
            try:
                # Execute the requested action, passing the route dictionary as
                # named parameters.
                if isAuthenticated:
                    getattr(controller, action)(**kargs)
            except :
                e = sys.exc_info()[1]
                controller.handle_exception(e, self.__debug)
                errMsg="%s:%s"%(type(e).__name__,e)
                response.set_status(500,errMsg)
                response.headers['ErrorMessage'] = errMsg
            if DEBUGGER_ENABLED is not None and isAuthenticated and session.getUser() and session.getUser().getSheetId() != 'guest' :
                pm.stop()
                logging.info('before appstats')
                JSON_str = pm.toJSON(url=request.path,user=session.getUser().getSheetId())
                logging.info(JSON_str)
                if JSON_str.__contains__('payload'):
                    saveDebugData(session,JSON_str,pm.timetaken(),pm.sheetmetadataname)
            response.wsgi_write(start_response)
#            logging.info('Time for this request %s'%(datetime.datetime.now() - st))
            return ['']
        else:
            response.set_status(404)

app = WSGIApplication(map, debug = True)
run_wsgi_app(app)