# coding: utf-8
from idm.core.workflow.sandbox.manager.user import userify
from idm.core.constants.workflow import DEFAULT_PRIORITY
from idm.core.workflow.plain.approver import (
    Approver as PlainApprover,
    AnyApprover as PlainAnyApprover
)
from idm.core.workflow.sandbox.manager.sanboxed import SandboxedMixin
from idm.core.workflow.sandbox.serializable import Serializable, serialize, deserialize


def flatten_approverify(approvers):
    # Копипаста из plain.approver, но с новыми классами
    for approver in approvers:
        if isinstance(approver, PlainAnyApprover):
            for other_approver in approver.approvers:
                yield Approver(other_approver)
        else:
            yield Approver(approver)


def approverify(approver):
    # Копипаста из plain.approver, но с новыми классами
    if isinstance(approver, (Approver, AnyApprover)):
        return approver
    return Approver(approver)


class Approver(SandboxedMixin, Serializable, PlainApprover):
    ALLOWED_METHODS = []
    ALLOWED_PROPERTIES = ['user']
    INITIAL_PROPERTIES = []

    @classmethod
    def from_dict(cls, data, context=None):
        username = data['username']
        notify = data['notify']
        priority = data['priority']
        return cls(username, notify, priority)

    def _as_dict(self):
        return {
            'username': self.username,
            'notify': self.notify,
            'priority': self.priority,
        }

    def __init__(self, username, notify=None, priority=None):
        if isinstance(username, PlainApprover):
            self._user = userify(username._user)
            self.username = username.username
            self.notify = username.notify
            self.priority = username.priority
        else:
            super(Approver, self).__init__(username, notify=notify, priority=priority)

    def __or__(self, other):
        return AnyApprover([self, other])

    @property
    def user(self):
        if not self._user:
            self._user = userify(self.username)
        return self._user


class AnyApprover(SandboxedMixin, Serializable, PlainAnyApprover):
    ALLOWED_METHODS = []
    ALLOWED_PROPERTIES = []
    INITIAL_PROPERTIES = []
    flatten_func = staticmethod(flatten_approverify)  # новая версия для песочницы

    def __init__(self, approvers, notify=None, priority=DEFAULT_PRIORITY):
        if isinstance(approvers, PlainAnyApprover):
            self.approvers = [Approver(x) for x in approvers.approvers]
            self.priority = approvers.priority
        else:
            super(AnyApprover, self).__init__(approvers, notify=notify, priority=priority)

    @classmethod
    def from_dict(cls, data, context=None):
        approvers = deserialize(data['approvers'], context=context)
        priority = data['priority']
        return cls(approvers, priority=priority)

    def _as_dict(self):
        return {
            'approvers': serialize(self.approvers),
            'priority': self.priority,
        }
