# coding: utf-8

import six

from idm.core.workflow.exceptions import NoGroupError
from idm.core.workflow.plain.group import (
    GroupWrapper as PlainGroupWrapper,
    ChainLevel as PlainChainLevel,
)
from idm.core.workflow.sandbox.manager.sanboxed import SandboxedMixin
from idm.core.workflow.sandbox.serializable import Serializable, serialize, deserialize
from idm.core.workflow.sandbox.manager.user import userify
from idm.users.models import Group


def groupify(thing):
    if thing is None:
        result = thing
    elif isinstance(thing, GroupWrapper):
        result = thing
    elif isinstance(thing, Group):
        result = GroupWrapper(thing)
    else:
        params = {}
        if isinstance(thing, six.integer_types):
            params['external_id'] = thing
        else:
            params['slug'] = thing
        try:
            result = GroupWrapper(Group.objects.user_groups().active().get(**params))
        except Group.DoesNotExist:
            raise NoGroupError('Подразделение {0} не существует.'.format(thing))
    return result


class ChainLevel(Serializable, PlainChainLevel):
    @classmethod
    def from_dict(cls, data, context=None):
        level = data['level']
        items = deserialize(data['items'], context=context)
        return cls(level, items)

    def as_dict(self):
        return {
            'level': self.level,
            'items': serialize([x for x in self])
        }


class AllList(Serializable, list):
    def all(self):
        return self

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

    def as_dict(self):
        return {
            'data': serialize(list(self))
        }


class GroupWrapper(SandboxedMixin, Serializable, PlainGroupWrapper):
    ALLOWED_METHODS = [
        'has_role', 'get_name', 'get_descendant_members',
        'get_parent', 'is_root', 'get_root', 'get_ancestor', 'get_ancestors', 'is_descendant_of', 'get_children',
        'get_chain_of_heads', 'get_all_responsibles', 'get_responsibles', 'get_heads', 'get_deputies', 'is_subgroup_of',
    ]
    ALLOWED_PROPERTIES = ['staff_id', 'parent', 'name', 'name_en', 'description', 'type', 'members', 'slug', 'head', 'level']
    INITIAL_PROPERTIES = ['slug', 'level', 'type', 'staff_id']

    userify_func = staticmethod(userify)
    chain_level_class = ChainLevel
    _user_wrapper = None

    @classmethod
    def get_user_wrapper(cls):
        if cls._user_wrapper is None:
            from idm.core.workflow.sandbox.manager.user import UserWrapper
            cls._user_wrapper = UserWrapper
        return cls._user_wrapper

    @classmethod
    def from_dict(cls, data, context=None):
        group_id = data['group_id']
        group = Group.objects.get(pk=group_id)
        return cls(group, context=context)

    def _as_dict(self):
        return {
            'group_id': self.group.id,
        }

    def get_chain_of_heads(self, *args, **kwargs):
        from idm.core.workflow.sandbox.manager.approver import AnyApprover
        plain_approvers = super(GroupWrapper, self).get_chain_of_heads(*args, **kwargs)
        return AnyApprover(plain_approvers)

    @property
    def members(self):
        return AllList((self.get_user_wrapper()(x) for x in super(GroupWrapper, self).__getattr__('members')))

    def get_descendant_members(self):
        return [self.get_user_wrapper()(x) for x in super(GroupWrapper, self).__getattr__('get_descendant_members')()]

    @property
    def head(self):
        return self.get_user_wrapper()(super(GroupWrapper, self).head)
