from parallels.core.utils.common.xml import seq, elem, text_elem
from parallels.core.utils.entity import Entity
from parallels.plesk.utils.xml_rpc.plesk import core


class TaskListInfo(Entity):
    TASK_STATUS_DONE = 'done'
    TASK_STATUS_ERROR = 'error'
    TASK_STATUS_BLOCKED = 'blocked'

    def __init__(self, task_id, node_id, status, status_message):
        self._task_id = task_id
        self._node_id = node_id
        self._status = status
        self._status_message = status_message

    @property
    def task_id(self):
        """Task ID

        :rtype: str | unicode
        """
        return self._task_id

    @property
    def node_id(self):
        """Node ID

        :rtype: str | unicode
        """
        return self._node_id

    @property
    def status(self):
        """Status of the task

        :rtype: str | unicode | None
        """
        return self._status

    @property
    def status_message(self):
        """Status message of the task: for example in case of failed task, this field is error message

        :rtype: str | unicode | None
        """
        return self._status_message


class NodeInfo(Entity):
    def __init__(self, node_id, ip):
        self._node_id = node_id
        self._ip = ip

    @property
    def node_id(self):
        """Node ID

        :rtype: str | unicode
        """
        return self._node_id

    @property
    def ip(self):
        """Main IP address of the node

        :rtype: str | unicode
        """
        return self._ip


class ExtensionCallOperator(object):
    class PleskMultiServer(object):
        class TaskListOperator(core.operation('GetTaskStatusOperator', ('filter_subscription_ids',))):
            operator_name = 'extension'
            operation_name = 'call'
            min_api_version = '1.6.8.0'
            max_api_version = None

            def inner_xml(self):
                return seq(
                    elem(
                        'plesk-multi-server', [
                            elem(
                                'task-list', [
                                    text_elem(
                                        'filter-subscription-id',
                                        ",".join([str(i) for i in self.filter_subscription_ids])
                                    )
                                ]
                            )
                        ]
                    )
                )

            @classmethod
            def parse(cls, elem):
                return core.Result.parse(elem.find('result'), cls._parse_data)

            @classmethod
            def _parse_data(cls, elem):
                return [
                    TaskListInfo(
                        task_id=task_status_elem.findtext('id'),
                        node_id=task_status_elem.findtext('node-id'),
                        status=task_status_elem.findtext('status'),
                        status_message=task_status_elem.findtext('status-message')
                    )
                    for task_status_elem in elem.findall('plesk-multi-server/task-list/task')
                ]

        class NodesListOperator(core.operation('NodesListOperator', ('filter_id',))):
            operator_name = 'extension'
            operation_name = 'call'
            min_api_version = '1.6.8.0'
            max_api_version = None

            def inner_xml(self):
                return seq(
                    elem(
                        'plesk-multi-server', [
                            elem(
                                'node-list', [
                                    text_elem(
                                        'filter-id',
                                        ",".join(
                                            str(node_id) for node_id in self.filter_id
                                        )
                                    )
                                ]
                            )
                        ]
                    )
                )

            @classmethod
            def parse(cls, elem):
                return core.Result.parse(elem.find('result'), cls._parse_data)

            @classmethod
            def _parse_data(cls, elem):
                return [
                    NodeInfo(
                        node_id=node_elem.findtext('id'),
                        ip=node_elem.findtext('ip')
                    )
                    for node_elem in elem.findall('plesk-multi-server/node-list/node')
                ]

        class PublicSSHKeyPutOperator(core.operation('PublicSSHKeyPutOperator', ('public_key',))):
            operator_name = 'extension'
            operation_name = 'call'
            min_api_version = '1.6.8.0'
            max_api_version = None

            def inner_xml(self):
                return seq(
                    elem(
                        'plesk-multi-server-node', [
                            elem(
                                'public-ssh-key-put', [
                                    text_elem('public-key', self.public_key)
                                ]
                            )
                        ]
                    )
                )

            @classmethod
            def parse(cls, elem):
                return core.Result.parse(elem.find('result'), cls._parse_data)

            @classmethod
            def _parse_data(cls, elem):
                return None

        class PublicSSHKeyDeleteOperator(core.operation('PublicSSHKeyRemoveOperator', ('public_key',))):
            operator_name = 'extension'
            operation_name = 'call'
            min_api_version = '1.6.8.0'
            max_api_version = None

            def inner_xml(self):
                return seq(
                    elem(
                        'plesk-multi-server-node', [
                            elem(
                                'public-ssh-key-delete', [
                                    text_elem('public-key', self.public_key)
                                ]
                            )
                        ]
                    )
                )

            @classmethod
            def parse(cls, elem):
                return core.Result.parse(elem.find('result'), cls._parse_data)

            @classmethod
            def _parse_data(cls, elem):
                return None
