import logging
import appconfig as config
from RenderTemplate import renderUploadPage,renderWSDL,renderSoapResponse,renderSoapFault
from BaseCommandFactory import BaseCommandFactory
from orangescape.model.engine.Component import Component
from orangescape.model.server.util.metadatautil import getRootBranchByName
from Validate import validateUser,validateCreate,validateUrl,validateUser_Read
from CommandUtil import dispatchCommand, getUrlParams, getResponseXSD,getXSD,authenticateIntegration

class CommandFactory(BaseCommandFactory):
    def invokeWS(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid):
        from xml.dom import minidom
        try:
            xmlString = self.request.body
            soapAction= self.request.headers["SOAPAction"].replace('"','')
            if 'Authorization' in self.request.headers:
                authorization= self.request.headers["Authorization"]
            else:
                self.response.out.write(renderSoapFault("Unable to authenticate.Auth info not present as part of the header."))
                return
            url=getUrlParams(self.request.path)
            metadataType=url.pop(0)
            url.pop()
            #get the last item(ie the sheetmetadataid) and get the sheet
            versionId=url[0]
            modifiedIn = url[2]
            parentSheetMetadataId=url.pop()
            self.getSession().setModifiedIn(modifiedIn)
            applicationObj = self.getSession().getApplication()
            #get parentsheetId and parentsheetMetadataId
            parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
            responseDict=authenticateIntegration(self.getSession(),authorization)
            if responseDict.has_key('error'):
                self.response.out.write(renderSoapFault(responseDict['error']))
                return
            rootNode=None
            from orangescape.model.server.integration.XMLImportService import XMLImportService
            component = Component(self.getSession())
            sheet=XMLImportService(component, parentSheetMetadata, xmlString).process()

            engine = Component(self.getSession())
            actDef=parentSheetMetadata.getActivityDefinitionById(modifiedIn)
            params = self.getQueryStringParams(self.request.query_string)
            formName = self.getEditorFormName(params, actDef, parentSheetMetadata)
            actionBranch=None
            try:
                actionBranch=getRootBranchByName(parentSheetMetadata,soapAction)
            except Exception, e:
                logging.warn('The action with action name %s not found'%(soapAction))
            if actionBranch:
                engine.executeAction(sheet,actionBranch)
            if soapAction=="Submit":
                engine.submit(sheet,actDef)
            params=getResponseXSD(self.getSession(), formName, parentSheetMetadata)
            response=renderSoapResponse(parentSheetMetadata.getSheetName(),"Update",sheet, params)
            xmldom=minidom.parseString(response)
            self.__commit__()
            self.response.headers['Content-Type'] = "text/xml"
            self.response.out.write(response)
            self.response.set_status(200)
        except Exception, e:
            self.response.out.write(renderSoapFault(str(e)))

    def wsdl(self,metadatatype,applicationid,parentsheetmetadataid,taskid,url):
        self.userid="guest"
        url=getUrlParams(self.request.path)
        location='/'.join(url)+"/ws"
        applicationId=url.pop(0)
        versionId=url.pop(0)
        sheetMetadata = url.pop(0)
        modifiedIn = url.pop(0)
        rootSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        actDef=rootSheetMetadata.getActivityDefinitionById(modifiedIn)
        params = self.getQueryStringParams(self.request.query_string)
#        formName = self.getEditorFormName(params, actDef, parentSheetMetadata)
        formName = self.getEditorFormName(params, actDef, rootSheetMetadata)
        actions = applicationObj.getActionMapping()[rootSheetMetadata.getSheetName()][formName]
        children = applicationObj.getFormMapping()[rootSheetMetadata.getSheetName()][formName]
        oneToManyList = children["root"]["OneToMany"]
        schemaDict={}
        relationShipDict={}
        getXSD(self.getSession(),oneToManyList,rootSheetMetadata,schemaDict,relationShipDict)
        #schemaDict[rootSheetMetadata.getSheetName()]=paramDict
#        logging.info(schemaDict)
        response = renderWSDL(location,rootSheetMetadata.getSheetName(),schemaDict,actions,relationShipDict)

        self.response.headers['Content-Type'] = 'application/xml'
        self.response.out.write(response)

    def csvimport(self, metadatatype, applicationid, parentsheetmetadataid, taskid, sheetmetadataid, url):
        """POST /Instances: User CSV Import"""
        url=getUrlParams(self.request.path)
        thefile = self.request.params['uploadedfile']

        file_name = thefile.filename
        content = thefile.value
        query_string = self.request.query_string

        #remove cvsimport string in the url
        url.pop()
        metadataType=url.pop(0)
        versionId=url[0]
        modifiedIn = url[2]
        rootSheetMetadataId=url[3]
        rootSheetId = url[4]

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        rootSheet=self.getSession().get(rootSheetId,rootSheetMetadata)
        validateUser(self.getSession(),applicationObj,url,rootSheet)

        sheetMetadataId=url.pop()
        referenceCellName=url.pop()
        parentSheetId=url.pop()
        parentSheetMetadataId=url.pop()
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId,parentSheetMetadata)

        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId);
        referenceCell = sheetMetadata.getPublicCellMetadata(referenceCellName)
        validateCreate(url,sheetMetadata,parentSheetMetadata,referenceCell)
        if(len(url)>0):
            validateUrl(url,applicationObj,parentSheet,parentSheetMetadata,self.getSession())

        params = self.getQueryStringParams(query_string)
        mappingGridCellId = params.get('gridCellId')

        from orangescape.model.server.integration.CsvImportService import UserCsvImportService
        from orangescape.model.server.Context import importMapping
        impMapping = importMapping.get(mappingGridCellId) or {}
        component = Component(self.getSession())
        logging.info('Importing %s under the parent %s'%(referenceCell.getSheetMetadata().getSheetName(), parentSheet.getSheetMetadata().getSheetName()))
        csvImportService = UserCsvImportService(component, parentSheet, referenceCell, impMapping)
        csvImportService.csvImport(content)
        self.__commit__()

        actDef=rootSheetMetadata.getActivityDefinitionById(modifiedIn)
        formName = self.getEditorFormName(params, actDef, rootSheetMetadata)
        jsonStr = self.returnResponse(self.getSession(), rootSheet, formName)
        self.response.out.write(jsonStr)

    def getAttachmentWithId(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        import mimetypes
        """GET /Instances/id: Show a specific item."""
        url=getUrlParams(self.request.path)
        fileName=url[len(url)-2]
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        versionId=url[0]
        modifiedIn = url[2]
        rootSheetMetadataId=url[3]
        rootSheetId = url[4]

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        rootSheet=self.getSession().get(rootSheetId,rootSheetMetadata)
        validateUser(self.getSession(),applicationObj,url,rootSheet)

        sheetId=url.pop()
        sheetMetadataId = url.pop()
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        sheet=self.getSession().get(sheetId, sheetMetadata)

        fileName,fileContent = dispatchCommand(self.getSession(),'getAttachmentWithId', sheet)
        fileSplit = fileName.split(".")
        mimetype = 'application/octet-stream'
        if len(fileSplit)>1:
            fileExtension = fileName.split(".")[1]
            mimetype = mimetypes.types_map.get("."+fileExtension.lower()) or 'application/octet-stream'
        self.response.headers['Content-Type'] = mimetype
        self.response.headers['Content-Disposition'] = 'inline; filename="%s"' % fileName
        if config.env==config.ENTERPRISE:
            self.response.out.write(fileContent.encode("ISO-8859-1"))
        else:
            self.response.out.write(fileContent)

    def updateAttachmentWithId(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        """POST /Instances: Create a new item."""
        if self.request.params.get('fileName'):
            file_name = self.request.params.get('fileName')
            file_value = self.request.params.get('fileContent')
            #file_value.encode("unicode-escape")
        else:
            thefile = self.request.params['uploadedfile']
            file_name = thefile.filename
            file_value = thefile.value

        updateOutput=self.perfromUpdateAttachmentWithId(file_name,file_value,self.request.query_string)
        if updateOutput:
            self.response.out.write(updateOutput)
        else:
            self.error(500)

    def perfromUpdateAttachmentWithId(self,fileName,fileContent,query_string):
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        versionId=url[0]
        modifiedIn = url[2]
        rootSheetMetadataId=url[3]
        rootSheetId = url[4]

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        rootSheet=self.getSession().get(rootSheetId,rootSheetMetadata)
        validateUser(self.getSession(),applicationObj,url,rootSheet)

        sheetId=url.pop()
        sheetMetadataId = url.pop()
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        sheet=self.getSession().get(sheetId, sheetMetadata)

        #need to revisit the validateUrl() for refCellName and modelName based REST Url
        isUpdated=dispatchCommand(self.getSession(),'updateAttachmentWithId', sheet, fileName, fileContent)
        self.__commit__()
        if isUpdated:
            actDef=rootSheetMetadata.getActivityDefinitionById(modifiedIn)
            params = self.getQueryStringParams(query_string)
            formName = self.getEditorFormName(params, actDef, rootSheetMetadata)
            return self.returnResponse(self.getSession(), rootSheet, formName)
        return None

    def deleteAttachmentWithId(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        versionId=url[0]
        modifiedIn = url[2]
        rootSheetMetadataId=url[3]
        rootSheetId = url[4]

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        rootSheet=self.getSession().get(rootSheetId,rootSheetMetadata)
        validateUser(self.getSession(),applicationObj,url,rootSheet)

        sheetId=url.pop()
        sheetMetadataId = url.pop()
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        sheet=self.getSession().get(sheetId, sheetMetadata)

        dispatchCommand(self.getSession(),'deleteAttachmentWithId', sheet)
        self.__commit__()

        actDef=rootSheetMetadata.getActivityDefinitionById(modifiedIn)
        params = self.getQueryStringParams(self.request.query_string)
        formName = self.getEditorFormName(params, actDef, rootSheetMetadata)
        response = self.returnResponse(self.getSession(), rootSheet, formName)
        self.response.out.write(response)

#******************************************************** bulk attachment ****************************************************************
    def attach(self,metadatatype,applicationid,parentsheetmetadataid,taskid,url):
        """POST /Instances: Create a new item."""
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        sheetMetadataId=url.pop()
        sheetMetadataRef=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)

#        validateUser(url)
        validateUser_Read(self.getSession(), applicationObj, url, parentSheetMetadata)
        if(len(url)>0):
            validateUrl(url,applicationObj,parentSheet,parentSheetMetadata,self.getSession())
        templatePath = 'upload.html'
        path = self.request.path
        path=path+"ment"
        response = renderUploadPage(templatePath,path)
        self.response.out.write(response)

    def updateAttachment(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        """POST /Instances: Create a new item."""
        updateOutput = self.performUpdateAttachment(self.request.body)
        if updateOutput:
            self.response.out.write(updateOutput)
        else:
            self.error(500)

    def performUpdateAttachment(self,fileContent):
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        fileName=url.pop()
        sheetMetadataId=url.pop()
        sheetMetadataRef=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #get parentsheetId and parentsheetMetadataId
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        referenceKeyCellMetadata = sheetMetadata.getCellMetadataById(sheetMetadataRef)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        validateUser_Read(self.getSession(), applicationObj, url, sheetMetadata)
#        validateUser(url)
        if(len(url)>0):
            validateUrl(url,applicationObj,parentSheet,parentSheetMetadata,self.getSession())
        isUpdated=dispatchCommand(self.getSession(),'updateAttachment', parentSheet, referenceKeyCellMetadata, fileName, fileContent)
        self.__commit__()
        if isUpdated:
            return True
        else:
            return False
#*********************************************************** unused methods *****************************************************************

    def attachWithId(self,metadatatype,applicationid,parentsheetmetadataid,taskid,url):
        """POST /Instances: Create a new item."""
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]
        rootSheetMetadataId=url[3]
        rootSheetId = url[4]

        sheetId=url.pop()
        sheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        sheet=self.getSession().get(sheetId, sheetMetadata)
        rootSheetMetadata=applicationObj.getSheetMetadataById(rootSheetMetadataId)
        rootSheet=self.getSession().get(rootSheetId, rootSheetMetadata)

        validateUser(self.getSession(),applicationObj,url,rootSheet)
        if len(url)>3:
            sheetMetadataRef=url[len(url)-1]
            parentSheetId = url[len(url)-2]
            parentSheetMetadataId=url[len(url)-3]

            #get parentsheetId and parentsheetMetadataId
            parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
            parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)
            referenceKeyCellMetadata = sheetMetadata.getCellMetadataById(sheetMetadataRef)

            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())

        elif(len(url)>0):
            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())

        templatePath = 'upload_file.html'
        path = self.request.path
        path=path+"ment"
        response = renderUploadPage(templatePath,path)
        self.response.out.write(response)

    def getAttachment(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        """GET /Instances/id: Show a specific item."""
        url=getUrlParams(self.request.path)
        fileName=url[len(url)-2]

        url=self.url
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        fileName=url.pop()
        sheetMetadataId=url.pop()
        sheetMetadataRef=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #get parentsheetId and parentsheetMetadataId
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        referenceKeyCellMetadata = sheetMetadata.getCellMetadataById(sheetMetadataRef)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        validateUser_Read(self.getSession(), applicationObj, url, sheetMetadata)

#        validateUser(url)
        if(len(url)>0):
            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())
        fileContent = dispatchCommand(self.getSession(),'getAttachment', parentSheet, referenceKeyCellMetadata, fileName)
        self.response.headers['Content-Type'] = 'application/octet-stream'
        self.response.headers['Content-Disposition'] = 'attachment; filename="%s.zip"' % fileName
        self.response.out.write(fileContent)

    def getAttachmentList(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        """GET /Instances/id: Show a specific item."""
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        sheetMetadataId=url.pop()
        sheetMetadataRef=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #get parentsheetId and parentsheetMetadataId
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        validateUser_Read(self.getSession(), applicationObj, url, sheetMetadata)
#        validateUser(url)
        if(len(url)>0):
            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())
        attachmentList=dispatchCommand(self.getSession(),'getAttachmentList', parentSheet, sheetMetadata)

        self.response.out.write(attachmentList)

    def deleteAttachment(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        """POST /Instances: Create a new item."""
        url=getUrlParams(self.request.path)

        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        fileName=url.pop()
        sheetMetadataId=url.pop()
        sheetMetadataRef=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #get parentsheetId and parentsheetMetadataId
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetId, parentSheetMetadata)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
#        validateUser(url)
        validateUser_Read(self.getSession(), applicationObj, url, sheetMetadata)
        if(len(url)>0):
            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())
        isDeleted=dispatchCommand(self.getSession(),'deleteAttachment', parentSheet, sheetMetadata,fileName)
        self.__commit__()
        if isDeleted:
            attachmentList=dispatchCommand(self.getSession(),'getAttachmentList', parentSheet, sheetMetadata)
            self.response.out.write(attachmentList)
        else:
            self.error(500)

    def deleteAllAttachments(self,metadatatype,applicationid,parentsheetmetadataid,taskid,sheetmetadataid,url):
        url=getUrlParams(self.request.path)
        #remove attach string in the url
        url.pop()
        metadataType=url.pop(0)
        #get the last item(ie the sheetmetadataid) and get the sheet
        versionId=url[0]
        modifiedIn = url[2]

        sheetMetadataId=url.pop()
        parentSheetId = url.pop()
        parentSheetMetadataId=url.pop()

        applicationObj = self.getSession().getApplication()
        self.getSession().setModifiedIn(modifiedIn)

        #get parentsheetId and parentsheetMetadataId
        parentSheetMetadata=applicationObj.getSheetMetadataById(parentSheetMetadataId)
        parentSheet=self.getSession().get(parentSheetMetadataId, parentSheetMetadata)

        #sheetMetadata=context.get('SheetMetadata', sheetMetadataId);
        sheetMetadata=applicationObj.getSheetMetadataById(sheetMetadataId)
        validateUser_Read(self.getSession(), applicationObj, url, sheetMetadata)
#        validateUser(url)
        if(len(url)>0):
            validateUrl(url,applicationObj,sheet,sheetMetadata,self.getSession())
        dispatchCommand(self.getSession(),'deleteAllAttachments', parentSheet, sheetMetadata)

#**********************************************************************************************************************************