from ultipa.types.types_response import Privilege

from ultipa.configuration.RequestConfig import RequestConfig
from ultipa.operate.base_extra import BaseExtra
from ultipa.types import  ULTIPA_RESPONSE, ULTIPA
from ultipa.utils import UQLMAKER, CommandList
from ultipa.utils.errors import ParameterException
from ultipa.utils.ResposeFormat import ResponseKeyFormat
from typing import List
from ultipa.structs.Policy import Policy
from ultipa.utils.convert import convertToPolicy
from ultipa.utils.convert import convertToPrivilege

JSONSTRING_KEYS = ["graphPrivileges", "systemPrivileges", "policies", "policy", "privilege"]
formatdata = ['graph_privileges']


class PolicyExtra(BaseExtra):
    '''
        Processing class that defines settings for policy related operations.
    '''

    def showPolicy(self,
                   requestConfig: RequestConfig = RequestConfig()) -> List[Policy]:
        '''
        Show policy list.

        Args:
            requestConfig: An object of RequestConfig class

        Returns:
            List[Policy]

        '''
        uqlMaker = UQLMAKER(command=CommandList.showPolicy, commonParams=requestConfig)
        res = self.UqlListSimple(uqlMaker=uqlMaker,
                                 responseKeyFormat=ResponseKeyFormat(jsonKeys=JSONSTRING_KEYS, dataFormat=formatdata))
        if len(res.data) > 0:
            res.data = convertToPolicy(res)
        return res.data

    def showPrivilege(self,
                      requestConfig: RequestConfig = RequestConfig()) -> Privilege:
        '''
        Show privilege list.

        Args:
            requestConfig: An object of RequestConfig class

        Returns:
            Privilege

        '''

        uqlMaker = UQLMAKER(command=CommandList.showPrivilege, commonParams=requestConfig)
        res = self.UqlListSimple(uqlMaker=uqlMaker,
                                 responseKeyFormat=ResponseKeyFormat(jsonKeys=JSONSTRING_KEYS))
        if len(res.data) > 0:
            res.data = convertToPrivilege(res)
        return res.data

    def getPolicy(self, policyName: str,
                  requestConfig: RequestConfig = RequestConfig()) -> Policy:
        '''
        Get a policy.

        Args:
            name: The name of policy

            requestConfig: An object of RequestConfig class

        Returns:
            Policy

        '''

        uqlMaker = UQLMAKER(command=CommandList.getPolicy, commonParams=requestConfig)
        uqlMaker.setCommandParams(policyName)
        res = self.UqlListSimple(uqlMaker=uqlMaker,
                                 responseKeyFormat=ResponseKeyFormat(jsonKeys=JSONSTRING_KEYS, dataFormat=formatdata))
        # if isinstance(res.data, list) and len(res.data) > 0:
        # 	res.data = res.data[0]
        if res.status.code == ULTIPA.Code.SUCCESS and res.data:
            res.data = convertToPolicy(res)
        return res.data

    def createPolicy(self, policy: Policy,
                     requestConfig: RequestConfig = RequestConfig()) -> ULTIPA_RESPONSE.UltipaResponse:
        '''
        Create a policy.

        Args:
            request:  An object of Policy class

            requestConfig: An object of RequestConfig class

        Returns:
            UltipaResponse

        '''

        uqlMaker = UQLMAKER(command=CommandList.createPolicy, commonParams=requestConfig)
        paramsP = [policy.name]
        if policy.graphPrivileges:
            paramsP.append(policy.graphPrivileges)
        else:
            paramsP.append({})

        if policy.systemPrivileges:
            paramsP.append(policy.systemPrivileges)
        else:
            paramsP.append([])

        if policy.policies:
            paramsP.append(policy.policies)
        else:
            paramsP.append([])

        if policy.propertyPrivileges:
            paramsP.append(policy.propertyPrivileges)
        else:
            paramsP.append({})

        uqlMaker.setCommandParams(paramsP)
        res = self.uqlSingle(uqlMaker=uqlMaker)
        return res

    def alterPolicy(self, policy: Policy,
                    requestConfig: RequestConfig = RequestConfig()) -> ULTIPA_RESPONSE.UltipaResponse:
        '''
        Alter a policy.

        Args:
            request:  An object of Policy class

            requestConfig: An object of RequestConfig class

        Returns:
            UltipaResponse

        '''

        uqlMaker = UQLMAKER(command=CommandList.alterPolicy, commonParams=requestConfig)
        uqlMaker.setCommandParams(policy.name)
        params = {}
        if policy.systemPrivileges is not None:
            params.update({"system_privileges": policy.systemPrivileges})
        if policy.graphPrivileges is not None:
            params.update({"graph_privileges": policy.graphPrivileges})

        if policy.policies is not None:
            params.update({"policies": policy.policies})

        if policy.propertyPrivileges is not None:
            params.update({"property_privileges": policy.propertyPrivileges})

        uqlMaker.addParam('set', params, notQuotes=True)
        res = self.uqlSingle(uqlMaker=uqlMaker)
        return res

    def dropPolicy(self, policyName: str,
                   requestConfig: RequestConfig = RequestConfig()) -> ULTIPA_RESPONSE.UltipaResponse:
        '''
        Drop a policy.

        Args:
            policyName:  Name of policy to be dropped
            requestConfig: An object of RequestConfig class

        Returns:
            UltipaResponse

        '''

        uqlMaker = UQLMAKER(command=CommandList.dropPolicy, commonParams=requestConfig)
        uqlMaker.setCommandParams(policyName)
        res = self.uqlSingle(uqlMaker=uqlMaker)
        return res

    def grantPolicy(self, userName: str = '', graphPrivileges: dict = None,
                    systemPrivileges: List[str] = None, policies: List[str] = None, propertyPrivileges: dict = None,
                    requestConfig: RequestConfig = RequestConfig()) -> ULTIPA_RESPONSE.UltipaResponse:
        '''
        Grant privileges and policies to a user.

        Args:
            username (str): The username to grant privileges and policies.

            graphPrivileges (dict): Dictionary containing graph privileges.

            systemPrivileges (List[str]): List of system privileges.

            policies (List[str]): List of policies to grant.

            propertyPrivileges(dict): Dictionary containing property privileges

            requestConfig (RequestConfig): An object of RequestConfig class

        Returns:
            UltipaResponse

        '''

        uqlMaker = UQLMAKER(command=CommandList.grantUser, commonParams=requestConfig)
        if userName:
            uqlMaker.setCommandParams(userName)
        else:
            raise ParameterException(err='username is a required parameter')

        paramsDict = {}
        if graphPrivileges:
            paramsDict.setdefault('graph_privileges', graphPrivileges)

        if systemPrivileges:
            paramsDict.setdefault('system_privileges', systemPrivileges)

        if policies:
            paramsDict.setdefault('policies', policies)

        if propertyPrivileges:
            paramsDict.setdefault('property_privileges', propertyPrivileges)

        uqlMaker.addParam('params', paramsDict, notQuotes=True)
        res = self.uqlSingle(uqlMaker=uqlMaker)
        return res

    def revokePolicy(self, userName: str = '', graphPrivileges: dict = None,
                     systemPrivileges: List[str] = None, policies: List[str] = None, propertyPrivileges: dict = None,
                     requestConfig: RequestConfig = RequestConfig()) -> ULTIPA_RESPONSE.UltipaResponse:
        '''
        Revoke privileges and policies from a user.

        Args:
            username (str): The username to revoke privileges and policies.

            graphPrivileges (dict): Dictionary containing graph privileges.

            systemPrivileges (List[str]): List of system privileges.

            propertyPrivileges(dict): Dictionary containing property privileges

            policies (List[str]): List of policies to revoke.

            requestConfig (RequestConfig): An object of RequestConfig class

        Returns:
            UltipaResponse

        '''

        uqlMaker = UQLMAKER(command=CommandList.revoke, commonParams=requestConfig)
        if userName:
            uqlMaker.setCommandParams(userName)
        else:
            raise ParameterException(err='username is a required parameter')

        paramsDict = {}
        if graphPrivileges:
            paramsDict.setdefault('graph_privileges', graphPrivileges)

        if systemPrivileges:
            paramsDict.setdefault('system_privileges', systemPrivileges)

        if propertyPrivileges:
            paramsDict.setdefault('property_privileges', propertyPrivileges)

        if policies:
            paramsDict.setdefault('policies', policies)
        uqlMaker.addParam('params', paramsDict, notQuotes=True)
        res = self.uqlSingle(uqlMaker=uqlMaker)
        return res
