import sys
import logging

from appconfig import LOG_LEVEL
logging.basicConfig(level=LOG_LEVEL)

from traceback import format_exception, format_exc
from google.appengine.ext.webapp import Request,Response
from org.springframework.web.context import ContextLoader
from org.springframework.orm.hibernate3 import SessionFactoryUtils

from orangescape.model.server.DbSession import DbSession

from orangescape.config.routing import make_map
from orangescape.model.server.Context import getApplication
import java.lang.Exception
from orangescape.gateway.wsgi import BaseWSGIApplication
from com.orangescape.logging import PersistenceLogger
logger = PersistenceLogger.getLogger()
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 __call__(self, environ, start_response, session):
        """Called by WSGI when a request comes in."""
        request = Request(environ)
        response = Response()

        application_relative_path=environ.get('PATH_INFO')
        if application_relative_path.__contains__('/attachment'):
            fileName,fileContent = getFileName_FileContent(environ)
        WSGIApplication.active_instance = self

        #initialize the command factory here
        full_path='/'+getApplication().getSheetId()+'/1'+application_relative_path
        controller,action,kargs = self.initializeCommandFactory(request, response, environ, session, full_path)

        if controller and action:
            # Execute the requested action, passing the route dictionary as
            # named parameters.
            exception = None
            try:
                if action == 'updateAttachmentWithId' or action == 'updateAttachment':
                    kargs['fileName'] = fileName
                    kargs['fileContent'] = fileContent

                jeerequest=environ['j2ee.request']
                controller.jeerequest = jeerequest

                #*********************json and xml truncation problem in enterprise*******************
                updateJson = jeerequest.getAttribute('updateJson')
                if action=='invoke' and updateJson:
                    kargs['updateJson']=updateJson

                soapRequestXML = jeerequest.getAttribute('soapRequestXML')
                if soapRequestXML:
                    kargs['soapRequestXML']=soapRequestXML
                #*************************************************************************************

                # Storing user id in http session
                userId = jeerequest.getSession().getAttribute('CurrentUser')
                if session.getUser() is None and userId:
                    userins=session.get(userId,getApplication().getSheetMetadata('User'))
                    session.setUser(userins)

                #do authentication
                isAuthenticated = False
                if 'section' in kargs:
                    if kargs['section'] == 'open':
                        isAuthenticated = True
                    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)


                if isAuthenticated:
                    getattr(controller, action)(**kargs)

                # Clearing http session
                if action == 'logout':
                    userId = None
                    jeerequest.getSession().setAttribute('CurrentUser',userId)
                elif userId is None and session.getUser() and session.getUser().getSheetId() != 'guest':
                    jeerequest.getSession().setAttribute('CurrentUser',session.getUser().getSheetId())

            except java.lang.Exception, e:
                exception=e
                logging.error("%s"%getJavaStackTrace(e))
            except :
                exception = sys.exc_info()[1]
                logging.error("%s"%getPythonTraceback())
            finally:
                if(exception):
                    controller.handle_exception(exception, self.__debug)
                    errMsg="%s:%s"%(type(exception).__name__,exception)
                    response.set_status(500,errMsg)
                    response.headers['ErrorMessage'] = errMsg
            response.wsgi_write(start_response)
            return ['']
        else:
            response.set_status(404)

def getFileName_FileContent(environ):
    if environ.__contains__('CONTENT_TYPE') and environ.get('CONTENT_TYPE').__contains__('multipart/form-data'):
        from org.apache.commons.fileupload import DiskFileUpload
        req = environ.get('j2ee.request')
        try:
            upload1 = DiskFileUpload()
            fileItem = upload1.parseRequest(req)
            iter = fileItem.iterator()
            while(iter.hasNext()):
                fileItm = iter.next()
#                from java.io import File;
#                from java.io import FileOutputStream;
#                from org.apache.commons.io import CopyUtils
#                f= File("E:/sample.gif");
#                out= FileOutputStream(f);
#                CopyUtils.copy(fileItm.getInputStream(),out);
#                out.close();
                return fileItm.getName(),fileItm.getString("ISO-8859-1")#str(fileItm.get())
        except:
            raise
    else:
        from com.orangescape.server.util import ServerUtil
        req = environ.get('j2ee.request')
        strBytes = ServerUtil.getStrBytes(req.getInputStream())
        return None,strBytes

def getPythonTraceback():
    import cStringIO
    from traceback import print_exc
    tmpFile=cStringIO.StringIO()
    print_exc(file=tmpFile)
    tb="%s"%tmpFile.getvalue()
    tmpFile.close()
    return tb.replace('\n','')

def getJavaStackTrace(t):
    import java.io.PrintWriter
    import java.io.StringWriter
    sw = java.io.StringWriter()
    pw = java.io.PrintWriter(sw)
    t.printStackTrace(pw)
    pw.flush()
    sw.flush()
    return sw.toString().replace('\n','')

def handler(environ, start_response):
    spring_context = ContextLoader.getCurrentWebApplicationContext()
    sessionFactory = spring_context.getBean("sessionFactory")
    db_session = SessionFactoryUtils.getSession(sessionFactory,True)
    if db_session is None:
        logging.error('springs session per thread is null!')
    session = DbSession(getApplication())
    session.setHSession(db_session)
    session.begin()
    try:
        app = WSGIApplication(map, debug = True)
        result = app(environ, start_response, session)
    except:
        logging.error('Unexpected error occured in WSGI Application:\n%s' % getPythonTraceback())
        raise
    finally:
        session.close()
    #This is done because session is committed and begun in places like user authentication. Need to check!
    return result