from orangescape.model.engine.execution.ProcessEngine import ProcessNode
from orangescape.model.engine.execution.ExecutionTree import ExecutionTree

from orangescape.model.server.util.metadatautil import getRootBranch
from orangescape.model.server.Interface import BaseNode
from orangescape.model.server.util.ServerUtil import __resolve_search_criteria__
import logging

class PrivateProcessNode(ProcessNode):

    def enter(self):
        privateType = self.args.get('PrivateType')
        if privateType=='Remote':
            self.__execute_remote_action__()
        elif privateType=='Child':
            self.__execute_child_action__()
        elif privateType=='Parent':
            self.__execute_parent_action__()

    def __execute_remote_action__(self):
        searchCriteria = self.args.get('Search-Criteria')
        privateBranch =  self.activityDefinition.getBranchList()[0]
        rMetadata = privateBranch.getSheetMetadata()
        logging.debug('Executing PrivateAction(rCall) from the sheet %s for the instance %s'%(self.sheet.getSheetMetadata().getSheetName(), self.sheet.getSheetId()))
        if searchCriteria:
            limit = int(self.args.get('limit') or 1000)
            contextCell = self.args.get('Context-CellName')
            if isinstance(contextCell, str) or isinstance(contextCell, unicode):
                contextCell = rMetadata.getCellMetadataById(contextCell)

            searchList = __resolve_search_criteria__(self.session, self.sheet, searchCriteria, limit)
            for rSheet in searchList:
                if contextCell:
                    logging.debug('Updating context-cell %s with the value %s for the Remote Sheet %s'%(contextCell, self.sheet.getSheetId(), rSheet.getSheetId()))
                    self.component.update(rSheet, {contextCell.getCellName():self.sheet.getSheetId()})

                self.component.executeAction(rSheet, privateBranch)
                if contextCell:
                    self.component.update(rSheet, {contextCell.getCellName():None})
        else:
            logging.warn('No Search-Criteria found for executing Private Action for Remote model for the instance %s'%self.sheet.getSheetId())

    def __execute_child_action__(self):
        referenceCell = self.args.get('Reference-Cell')
        searchCriteria = self.args.get('Child-Search-Criteria')

        if searchCriteria is None:
            searchCriteria = self.args.get('Search-Criteria')

        childList = None
        if searchCriteria:
            rootNode = BaseNode()
            et = ExecutionTree(self.session)
            et.resolveRHS(searchCriteria, self.sheet, rootNode)
            childList = self.session.filter(self.sheet, referenceCell, rootNode)
        else:
            childList = self.session.getList(self.sheet, referenceCell)

        privateBranch =  self.activityDefinition.getBranchList()[0]
        childMetadata = referenceCell.getSheetMetadata()
        orderBy = childMetadata.getPublicCellMetadata('CreatedAt')
        reverse = False
        if orderBy:
            childList.sort(lambda x, y:cmp(x.get(orderBy), y.get(orderBy)), reverse=reverse)

        for child in childList:
            logging.debug('Executing PrivateCommand for child for the instance %s'%(child.getSheetName()))
            self.component.executeAction(child, privateBranch)

    def __execute_parent_action__(self):
        referenceCell = self.args.get('Reference-Cell')
        parentMetadata = referenceCell.getReferredSheetMetadata()

        if self.sheet.get(referenceCell) is not None and str(self.sheet.get(referenceCell)).strip() != '':
            parentSheet = self.session.get(self.sheet.get(referenceCell), parentMetadata)
            privateBranch =  self.activityDefinition.getBranchList()[0]
            logging.debug('Executing PrivateCommand for parent for the instance %s'%(parentSheet.getSheetName()))
            self.component.executeAction(parentSheet, privateBranch)