import logging
import datetime
import sys
import clr
clr.AddReferenceToFile('orangescape.dll')
from orangescape import GatewayInterface
import scriptwrapper as script
from SessionFactoryGFS import buildSessionFactory,getSLInstance,getPrimarySession,getSecondarySession
from orangescape.config.routing import make_map
from orangescape.rc.mock.webob import Request
from orangescape.rc.mock.webob import Response
from SLUtils import hostname
from orangescape.gateway.wsgi import BaseWSGIApplication


class WSGIApplication(GatewayInterface, BaseWSGIApplication):
    mapper = None
    sessionFactory = None
    def __init__(self):
        self.mapper = make_map()
        startTime = datetime.datetime.now()
        appId = script.invoke_script('getAppId')
        userId = script.invoke_script('getUserId')
        workingSheetId = script.invoke_script('getPortalSelectedSheet')
        releaseId = script.invoke_script('getReleaseId')

        initParams = eval(script.invoke_script('getInitParams') or "{}")
        sheetIds = eval(script.invoke_script('getSheetIdList') or "{}")
        newSheetQs = script.invoke_script('getNewSheetQs')

        self.sessionFactory = buildSessionFactory(appId, userId, workingSheetId, sheetIds, releaseId, initParams, newSheetQs)
        logging.info('Registering the objects....')
        self.__register_objects__(self.sessionFactory)
        if hostname==':-1':
            self.sessionFactory.on_download_finish()
        logging.debug('Time to load the application '+str(datetime.datetime.now()-startTime))

    def __register_objects__(self, sessionFactory):
        script.register_scriptableObject("instance", sessionFactory.getSLInstance())
        script.register_scriptableObject("primarySession", sessionFactory.getPrimarySession())
        script.register_scriptableObject("secondarySession", sessionFactory.getSecondarySession())

        script.register_scriptableObject("slwsgi", self)

    def postInitialize(self,controller, kargs):
        controller.setSecondarySession(self.sessionFactory.getSecondarySession())
        controller.setMetadataType(kargs.get('metadatatype'))
        if kargs.get('metadatatype') == '3' or kargs.get('metadatatype') == '4':
            controller.setTransientSession(self.sessionFactory.getTransientSession())
            #since we launch worktop directly if guest is not avaialble we need to create guest
            if controller.getSession().getUser() is None:
                controller.setUserId('guest')
        if 'section' in kargs:
            del kargs['section']
        for key in kargs:
            if key.__contains__("___"):
                del kargs[key]
                break;

    def dispatch(self, url, query_string="", methodType="GET"):
        logging.info("%s?methodType=%s&%s"%(url,methodType,query_string))
        environ = {"REQUEST_METHOD":methodType,"PATH_INFO":url,"QUERY_STRING":query_string}
        request = Request(environ)
        response = Response()
        controller = None
        try:
            controller,action,kargs = self.initializeCommandFactory(request, response, environ, self.sessionFactory.getPrimarySession(), request.path)
            if controller and action:
                if request.params.get('userId'):
                    controller.setUserId(request.params.get('userId'))
                getattr(controller, action)(**kargs)
                return response.wsgi_write()
            else:
                response.set_status(404)
        except :
            e = sys.exc_info()[1]
            errorTrace = ""
            for line in StackTraceFromCurrentException():
                logging.error(formatLine(line))
                errorTrace += formatLine(line)
            errorMessage = e.__class__.__name__ + ": " + str(e)
            #if len(errorMessage)>1000:
                #errorMessage = errorMessage[:1000]
            logging.error(errorMessage)
            script.invoke_script('userErrorAlert', errorMessage, errorTrace)
            if controller:
                controller.rollback()

def StackTraceFromCurrentException():
    traceback = sys.exc_info()[2]
    stackTrace = []
    while traceback is not None:
        frame = traceback.tb_frame
        lineno = traceback.tb_lineno
        code = frame.f_code
        filename = code.co_filename
        name = code.co_name
        stackTrace.append((filename, lineno, name))
        traceback = traceback.tb_next
    sys.exc_clear()
    return stackTrace

def formatLine(lineInfo):
    fileName, lineNo, name = lineInfo
    line = '  File "%s", line %s, in %s' % (fileName, lineNo, name)
    return line