import logging
from orangescape.model.engine.execution.ProcessUtil import getAssignedUser
from orangescape.model.engine.execution.ProcessUtil import getProcessCell_PrefixName
import appconfig as config

"""
Sample URL: /os/purchaseorder/poo1/purchaseorder/linteitem/loo1/primary_product/product
"""
def validateCreate(url,sheetMetadata,parentSheetMetadata,referenceKey):
    hasRelationShip=False
    for referredCellmetadata in sheetMetadata.getManyToOneList():
     if referredCellmetadata.getSheetName()==referenceKey.getSheetName() and referredCellmetadata.getReferredSheetMetadata().getSheetId()==parentSheetMetadata.getSheetId():
       hasRelationShip=True

    if not hasRelationShip:
       for referredCellmetadata in sheetMetadata.getOneToManyList():
            if referredCellmetadata.getSheetName()==referenceKey.getSheetName() and referredCellmetadata.getSheetMetadata().getSheetId()==parentSheetMetadata.getSheetId():
               hasRelationShip=True

    if not hasRelationShip:
        raise Exception(parentSheetMetadata.getSheetMetadataName()+" cannot be reached through "+sheetMetadata.getSheetMetadataName()+".Please check the URL")
def validateUser_Read(session, applicationObj, url,rootSheet=None):
    version=url.pop(0)
    parentSheetMetadata=url.pop(0)
    activityDef=url.pop(0)

def validationSubscribedUser(session, userSheetMetadata, assignedUserId_email, subscriptionList):
    getMultiDict = dict()
    for subUser in subscriptionList:
        getMultiDict[subUser.getValue('User')] = userSheetMetadata.getSheetId()
    userList = session.getMulti(getMultiDict)
    for user in userList:
        if userList[user].getValue('SheetName') == assignedUserId_email.lower():
            return True
        elif userList[user].getSheetId() == assignedUserId_email:
            return True

def __isAuthorized_user__(session, applicationObj, activityDef, rootSheet=None,piId=None):
    if config.env != config.SL:
        if session.getUser().getValue('IsAdmin'):
            return True
        userSheetMetadata = applicationObj.getSheetMetadata('User')
        processCellPrefix = getProcessCell_PrefixName(activityDef)
        prefix_tenant = ''
        if activityDef.getActivityTenant() or activityDef.containsActivityTenantFormula():
            prefix_tenant = processCellPrefix
        if session.getUser().getValue('Company') != rootSheet.getValue(prefix_tenant+'Tenant'):
            return False
        if rootSheet:
            if rootSheet.getValue(processCellPrefix+'Status') != activityDef.getSheetId():
                return False
            assignedTo = rootSheet.getValue(processCellPrefix+'AssignedTo')
            if assignedTo:
                if activityDef.getAssignedFor() == 'User' and assignedTo == session.getUser().getValue('UserId').split('@')[0]:
                    return True
                elif __isAuthorized_User_for_Group__(session,applicationObj,assignedTo):
#                    if activityDef.getAssignedTo() is not None:
#                    logging.info('Validating instance %s(%s) for the AppRole %s'%(rootSheet.getSheetId(), rootSheet.getSheetMetadata().getSheetName(), assignedTo))
                    return __isAuthorized_User_for_Group__(session,applicationObj,assignedTo)
                elif piId :
                    processInstanceMetadata = applicationObj.getSheetMetadata('ProcessInstance')
                    processInst =  session.get(piId,processInstanceMetadata)
                    if processInstanceMetadata.getPublicCellMetadataDict().__contains__('DelegatedTo') and processInst.getValue('DelegatedTo') == session.getUser().getValue('UserId').split('@')[0]:
                        return True
                return False
    return True

def __isAuthorized_User_for_Group__(session,applicationObj,assignedTo):
     from orangescape.model.server.util.ServerUtil import validateGroup
     roleSubscriptionMetadata = applicationObj.getSheetMetadata('RoleSubscription')
     if validateGroup(assignedTo, session.getList(session.getUser(),roleSubscriptionMetadata.getPublicCellMetadata('PrimaryUser'))):
        return True
     elif validateGroup(assignedTo, session.getList(session.getUser(),roleSubscriptionMetadata.getPublicCellMetadata('SecondaryUser'))):
        return True
     return False

def validateUser(session, applicationObj, url, rootSheet=None, piId=None):
    version = url.pop(0)
    parentSheetMetadata = url.pop(0)
    activityId = url.pop(0)
    rootSheetMetadata = applicationObj.getSheetMetadataById(parentSheetMetadata)
    searchDef = None
    if activityId == 'report':
        searchDefId = url.pop(0)
        searchDef =  rootSheetMetadata.getSearchDefinitionById(searchDefId)
        assignedTo = searchDef.getValue('AssignedTo')
        if not assignedTo:
            return True
        if assignedTo and __isAuthorized_User_for_Group__(session,applicationObj,assignedTo):
            return True
    else:
        activityDef = rootSheetMetadata.getActivityDefinitionById(activityId)
        if __isAuthorized_user__(session, applicationObj, activityDef, rootSheet,piId):
            return True
    if searchDef:
        raise Exception("The user "+ session.getUser().getSheetName()+"["+session.getUser().getSheetId()+"]"+" does not have permission to access the report "+searchDef.getSheetName())
    else:
        raise Exception("The user "+ session.getUser().getSheetName()+"["+session.getUser().getSheetId()+"]"+" does not have permission to access the task "+activityDef.getSheetName())

def validateUrl(url,application,sheet,sheetMetadata,session):

    """
    First check whether the type of relation ship between the sheet metadata and its parent sheet metadata.
    Depending on the relationship type check the sheet reference from the many side.
    if the reference is not found in many side throw exception.
    """
    referenceKey=url.pop()
    parentSheetId=url.pop()
    parentSheetMetadataId=url.pop()
#    referenceKeyCellMetadata=ServerUtil.get('CellMetadata', referenceKey);
    parentSheetMetadata=application.getSheetMetadataById(parentSheetMetadataId)
    parentSheet=session.get(parentSheetId,parentSheetMetadata)

    isManyToOneInstance=False
    isOneToManyInstance=False

    #POMetadata/p001/LIRefCell/LIMetadata
    referredCellmetadataList = [cellMetadata for cellMetadata in sheetMetadata.getManyToOneList() if cellMetadata.getSheetId()==referenceKey]
    if len(referredCellmetadataList)>0:
         referredCellmetadata=referredCellmetadataList.pop();
#         logging.info("the many to one list "+str(sheetMetadata.getManyToOneList()) +"  "+referredCellmetadata.getReferredSheetMetadata().getSheetId()+"  "+parentSheetMetadata.getSheetId())
         if referredCellmetadata.getReferredSheetMetadata().getSheetId()==parentSheetMetadata.getSheetId():
             isManyToOneInstance=True

    if not isManyToOneInstance:
        #LIMetadata/li001/LIRefCell/PRODMetadata
        referredCellmetadataList = [cellMetadata for cellMetadata in sheetMetadata.getOneToManyList() if cellMetadata.getSheetId()==referenceKey]
        if len(referredCellmetadataList)>0:
             referredCellmetadata=referredCellmetadataList.pop();
             if referredCellmetadata.getSheetMetadata().getSheetId()==parentSheetMetadata.getSheetId():
                 isOneToManyInstance=True

    if not isOneToManyInstance and not isManyToOneInstance:
        raise Exception("Invalid URL. "+sheetMetadata.getSheetMetadataName()+" instance is not related to "+ parentSheetMetadata.getSheetMetadataName() +" instance")

    if isManyToOneInstance:
        if not sheet.get(referredCellmetadata)==parentSheet.getSheetId():
            raise Exception("Invalid URL. "+parentSheetMetadata.getSheetMetadataName()+" instance is not related to "+ sheetMetadata.getSheetMetadataName() +" instance")
#    logging.info("Validate URL :"+parentSheet.getSheetId()+"  "+str(referredCellmetadata) +"  "+sheet.getSheetId())
    if isOneToManyInstance:
        if not parentSheet.get(referredCellmetadata)==sheet.getSheetId():
            raise Exception("Invalid URL. "+sheetMetadata.getSheetMetadataName()+" instance is not related to "+ parentSheetMetadata.getSheetMetadataName() +" instance")
    if len(url) >0:
        validateUrl(url,application,parentSheet,parentSheetMetadata,session)
