from CommandFactory import CommandFactory
import appconfig as config
import logging
from orangescape.model.server.Constants import JSON_RESPONSE,HTML_RESPONSE, INBOX, EDITOR, WORKTOP
from orangescape.model.server.util.formserialization import  serializeStyle
from RenderTemplate import renderTemplate
from orangescape.model.server.util.JstlSerialization import JstlGenerator
from orangescape.model.server.util.TemplateUtil import Helper
from orangescape.model.server.util.ServerUtil import _get_class
from CommandUtil import dispatchCommand
if config.env==config.SL:
    import scriptwrapper as script
else:
    from orangescape.tests.mock import MockScriptObject as script

portlet_module_package = "TemplateUtil.%sPortlet"

class SLCommandFactory(CommandFactory):
    secondarySession = None
    primarySession = None
    transientSession = None
    metadatatype = '1'

    def initialize(self, request, response):
        self.request = request
        self.response = response

    def setUserId(self, userid):
        from UserAuthentication import UserAuthentication
        userinitialization=UserAuthentication(self.getSession(), userid)
        if userid == "guest":
            #since we launch worktop directly if guest is not avaialble we need to create guest
            self.userid = userid
            userinitialization.initialize()
        else:
            self.userid=userinitialization.authenticateUser()
        userins=self.getSession().get(self.userid,self.getSession().getApplication().getSheetMetadata('User'))
        #need to revisit it,temporary code since when creating a new user record guest is getting created without company reference
        if userid == "guest" and userins.getValue("Company") is None:
            from Component import Component
            component=Component(self.getSession())
            companyins = component.new(self.getSession().getApplication().getSheetMetadata('Company'), {'SheetName':'OS'},'OS')
            component.update(userins, {'Company':companyins.getSheetId(), 'Tenant':companyins.getSheetId()})
        self.getSession().setUser(userins)
        #while preview login if they type the user which is already part of secondary data then we need to check the below information
        # ------------------------------ generating subcribed user to show worktop items --------------------------------
#        roleSubscriptionMetadata = self.getSession().getApplication().getSheetMetadata('RoleSubscription')
#        user_subscribedUser_refCell = roleSubscriptionMetadata.getPublicCellMetadata('PrimaryUser')
#        subscriptionList=self.getSession().getList(userins, user_subscribedUser_refCell)
#        hasPrimaryUser = False
#        if len(subscriptionList) > 0:
#            for subUser in subscriptionList:
#                if subUser.getValue('PrimaryUser')== userins.getSheetId():
#                    hasPrimaryUser = True
#                    break;
#        if not hasPrimaryUser:
#            dispatchCommand(self.getSession(),'create', userins, user_subscribedUser_refCell)
        # -------------------------------------------------------------------------------------------------------------------

    def setSession(self, psession):
        self.session = psession
        #need to remove
        self.primarySession = psession

    def setSecondarySession(self, secSession):
        self.secondarySession = secSession

    def getSession(self):
        if(self.getMetadataType() == '1'):
            return self.getPrimarySession()
        elif(self.getMetadataType() == '2'):
            return self.getSecondarySession()
        elif(self.getMetadataType() == '3' or self.getMetadataType() == '4'):
            return self.getTransientSession()

    def getSecondarySession(self):
        return self.secondarySession

    def getPrimarySession(self):
        return self.primarySession

    def setTransientSession(self, tSession):
        self.transientSession = tSession

    def getTransientSession(self):
        return self.transientSession

    def setMetadataType(self, metadatatype):
        self.metadatatype = metadatatype

    def getMetadataType(self):
        return self.metadatatype

    def getEditorFormName(self, params, actDef, sheetMetadata):
        if(self.getMetadataType() == '3' or self.getMetadataType() == '4'):
            return CommandFactory.getEditorFormName(self, params, actDef, sheetMetadata)
        return 'DummyGridView'

    def __commit__(self):
        if self.getMetadataType() == '3' or self.getMetadataType() == '4':
            self.getTransientSession().commit()
        else:
            self.getPrimarySession().commit()
            self.getSecondarySession().commit()
            config.undoCounter+=1
            if config.undoCounter-config.base>config.STACK_SIZE:
                config.base=config.undoCounter-config.STACK_SIZE
            config.commitCounter+=1
            if self.isNewModel():
                if not config.commitCounter % 5:
                    script.invoke_script('userMessage', 'You are working in Newly created Model. Click Save in Server.', 5000, 'Unsaved Model')
#            self.enable('save_draft')
#            self.enable('save_in_server')
            logging.info('SLCommandFactory __commit__')
            script.invoke_script('update_save_status', 0)
            self.disable('redo')
            self.enable('undo')

    def rollback(self):
        self.getPrimarySession().rollback()
        self.getSecondarySession().rollback()

# ************************************************************ helper methods *************************************************************
    def getMimeType(self):
        if self.request.params.get('mimetype') == HTML_RESPONSE:
            return HTML_RESPONSE
        return JSON_RESPONSE

    def redirect(self, uri, permanent=False):
        from app import getSLWsgi
        self.response.out.write(getSLWsgi().dispatch(uri))

    def renderWorktop(self,metadatatype,applicationid):
        userMetadata=self.getSession().getApplication().getSheetMetadata('User')
        userins = self.getSession().getUser()

        workflowBranch=userMetadata.getWorkFlowRoot()
        startActivity=workflowBranch.getActivityDefinitionList()[0]
        jsonUrl = '/'+self.getSession().getApplication().getSheetId()+'/3/'+userMetadata.getSheetId()+'/'+startActivity.getSheetId()+'/'+userMetadata.getSheetId()+'/'+userins.getSheetId()

        #to assign formmapping and actionmapping to application
        actDefId = userins.getValue('Status')
        if actDefId:
            actDefinition = userMetadata.getActivityDefinitionById(actDefId)
            gridViewId = self.getEditorGridViewId(userMetadata, actDefinition.getFinalEditorGridView())
            formJstl = self.getGridViewJstl(gridViewId)
        else:
            gridViewId = self.getEditorGridViewId(userMetadata, startActivity.getFinalEditorGridView())
            formJstl = self.getGridViewJstl(gridViewId)

        templateDict = self.getBaseTemplateDict(WORKTOP, jsonUrl)
        response = renderTemplate('preview_index.html',templateDict,self)
        self.response.out.write(response)

    def renderLogin(self, metadatatype, applicationid):
        userInstanceList = list()
        userMetadata = self.getSession().getApplication().getSheetMetadata('User')
        for userInstance in self.getSession().query(userMetadata):
            if userInstance.getSheetId() != 'guest':
                userInstanceList.append(userInstance)
        templateDict = self.getBaseTemplateDict()
        templateDict['userList'] = userInstanceList
        htmlStr = renderTemplate('preview_login.html',templateDict,self)
        self.response.out.write(htmlStr)

    def getEditorGridViewId(self, sheetMetadata, formName):
        gridViewList = sheetMetadata.getGridViewList()
        for gridViewId,gridViewName in gridViewList.iteritems():
            if gridViewName == formName:
                return gridViewId

    def getInboxGridViewId(self, sheetMetadata, formName):
        gridViewList = sheetMetadata.getQGridViewList()
        for gridViewId,gridViewName in gridViewList.iteritems():
            if gridViewName == formName:
                return gridViewId

    def updateFormMapping(self, sheetMetadata, formName, formMappingDict):
        secSession = self.getTransientSession()
        formMapping = dict()
        formMapping[sheetMetadata.getSheetName()] = dict()
        formMapping[sheetMetadata.getSheetName()][formName] =formMappingDict
        secSession.getApplication().setFormMapping(formMapping)

    def updateActionMapping(self, sheetMetadata, formName, actionMappingDict):
        secSession = self.getTransientSession()
        actionMapping = dict()
        actionMapping[sheetMetadata.getSheetName()] = dict()
        actionMapping[sheetMetadata.getSheetName()][formName] = actionMappingDict
        secSession.getApplication().setActionMapping(actionMapping)

    def returnResponseOnNew(self, session, root, formName):
        editorGirdViewId = self.getEditorGridViewId(root.getSheetMetadata(), formName)
        self.getGridViewJstl(editorGirdViewId)
        return CommandFactory.returnResponseOnNew(self, session, root, formName)

    def returnResponse(self, session, root, formName):
        if self.getMimeType()==HTML_RESPONSE and self.getMetadataType() != 1:
            url_path = self.request.path#+"?form="+formName
            editorGridViewId = self.getEditorGridViewId(root.getSheetMetadata(), formName)
            templateDict = self.getBaseTemplateDict(EDITOR, url_path, formName, editorGridViewId, root.getSheetMetadata())
            return renderTemplate('preview_index.html',templateDict,self)
        else:
            return CommandFactory.returnResponse(self, session, root, formName)

    def returnSearchResponse(self, sheetmetadata, searchDef, formName, pageNumber, pageCount, typeName, searchResult=None, serializeChildRecord=False, totalCount = 0):
        inboxGridViewId = self.getInboxGridViewId(sheetmetadata, formName)
        if self.getMimeType()==HTML_RESPONSE and self.getMetadataType() != 1:
            url_path = self.request.path
            #need to handled if page number and page size is not specified(backward compatibility)
            if pageNumber is None:
                url_path += "/p1/"
            if pageCount is None:
                pageCount=20
                if searchDef.getItemsPerPage():
                    pageCount = int(searchDef.getItemsPerPage())
                url_path += str(pageCount)
            templateDict = self.getBaseTemplateDict(typeName, url_path, formName, inboxGridViewId, sheetmetadata)
            return renderTemplate('preview_index.html',templateDict,self)
        else:
            return CommandFactory.returnSearchResponse(self, sheetmetadata, searchDef, formName, pageNumber, pageCount, typeName, searchResult, serializeChildRecord, totalCount)

    def getBaseTemplateDict(self, typeName=EDITOR, jsonUrl=None, formName=None, gridViewId=None, sheetMetadata=None):
        templateDict = dict()
        formJstl = ''
        css = ''
        if gridViewId:
            formJstl = self.getGridViewJstl(gridViewId, typeName)
            css = self.getCssString()
        elif formName:
            #need to revisit the below code for custom form preview,
            #only formmapping is needed,action is not available for custom form
            formJstl = script.invoke_script('getFormContent')
            formMappingStr = script.invoke_script('getFormMapping')
            #updating formmapping part of application
            self.updateFormMapping(sheetMetadata, formName, eval(formMappingStr))
            css = self.getCssString()

        if jsonUrl:
            portlet =  _get_class(portlet_module_package%typeName)(self, typeName+"001",jsonUrl, None, formName)
            templateDict['portlet']= portlet

        templateDict['formJstl'] = formJstl
        templateDict['css']= css
        helper = Helper()
        helper.setHomeUrl("javascript:writeToDocument('/"+self.getSession().getApplication().getSheetId()+"/3/worktop')")
        helper.setLogoutUrl("javascript:studioWindow.setSelectedUserId(null);writeToDocument('/"+self.getSession().getApplication().getSheetId()+"/3/signin')")
        helper.setMetadataType(self.getMetadataType())
        templateDict['helper'] = helper
        return templateDict


    def getGridViewJstl(self, gridViewId, typeName=EDITOR):
        try:
            session = self.getPrimarySession()
            #this should be replaced by transient session
            secSession = self.getTransientSession()

            sheetMetadata = session.getApplication().getSheetMetadata('SheetMetadata')
            gridViewMetadata = session.getApplication().getSheetMetadata('GridView')
            gridView = session.get(gridViewId, gridViewMetadata)
            sheetMetadataId = gridView.getValue('SheetMetadata')
            if typeName == INBOX:
                sheetMetadataId = gridView.getValue('QSheetMetadata')
            sheet = session.get(sheetMetadataId,sheetMetadata)
            jstlGenerator = JstlGenerator(session)
            jstlGenerator.build(gridView)
            formJstl = jstlGenerator.JSTL

            #update action and formmapping part of application, need to remove after transient session is implemented
            self.updateFormMapping(sheet, gridView.getSheetName(), jstlGenerator.formSerializeTable)
            self.updateActionMapping(sheet, gridView.getSheetName(), jstlGenerator.actionMappingTable)
            return formJstl
        except :
            raise

    def getCssString(self):
        session = self.getPrimarySession()
        #generating application.css as css string
        appId = self.getSession().getApplication().getSheetId()
        #logging.info('Getting appId %s'%(appId))
        devApplication = self.getPrimarySession().get(appId, self.getPrimarySession().getApplication().getSheetMetadata('Application'))
        css=''
        for style in session.getList(devApplication, session.getApplication().getSheetMetadata('Style').getPublicCellMetadata('Application')):
            jsonStr = serializeStyle(session,style,session.getApplication().getSheetMetadata('Style'))
            css=css+jsonStr
        return css

    def isNewModel(self):
        return self.getPrimarySession().isNewModel()

    def disable(self, buttonName):
#        logging.info('disable '+buttonName)
        script.invoke_script('disableImage',buttonName)

    def enable(self, buttonName):
#        logging.info('enable '+buttonName)
        script.invoke_script('enableImage',buttonName)

    def queryByTable(self, metadatatype, applicationid, sheetmetadataid):
        from orangescape.model.server.util.ReportSerializer import serializeAggregatedData
        from orangescape.model.server.util.json import write

        from CommandUtil import getUrlParams

        urlParamList=getUrlParams(self.request.path)
        urlParamList.pop()
        query_string=self.request.query_string
        values=self.getQueryStringParams(query_string)
        metadataId = urlParamList.pop()
        metadata = self.getSession().getApplication().getSheetMetadataById(metadataId)

        bQyeryStr = values.get('basequery')
        baseQuery = list()
        if bQyeryStr:
            bQuery = eval(bQyeryStr)            
            baseQuery =  bQuery

        if values.has_key('limit'):
            limit = int(values.get('limit'))
        else:
            limit = 100000

        dimensionStr = values.get('dimensions')
        if dimensionStr:
            """Aggregate query"""
            logging.info('dimension Str %s'%dimensionStr)
            dimensions = eval(dimensionStr)
            measures = eval(values.get('measures') or '[]')
            operations = eval(values.get('operations') or '[]')
            jsonStr = write(self.getSession().aggregate_query(metadata, limit, baseQuery, measures, dimensions, operations))
            logging.info('json %s'%(jsonStr))
            self.response.out.write(self.getJsonForJsonp(jsonStr))
        else:
            """normal query"""
            self.response.out.write("{}")



