# coding: utf-8

import attr


@attr.s(slots=True)
class Requester(object):
    impersonated = attr.ib()  # _requester, если передано, или текущий пользователь, если нет
    impersonator = attr.ib(default=None)  # текущий пользователь, если передан _requester, иначе None
    allowed_systems = attr.ib(default=None)

    def is_impersonated(self):
        return self.impersonator is not None

    def is_allowed_for(self, system):
        return self.allowed_systems is None or system in self.allowed_systems

    def __str__(self):
        result = 'Requester "%s"' % self.impersonated.username
        if self.is_impersonated():
            result += '[impersonated by: "%s"]' % self.impersonator.username
        return result

    def as_dict(self):
        return {
            'impersonated': self.impersonated.username if self.impersonated else None,
            'impersonator': self.impersonator.username if self.impersonator else None,
            'allowed_systems': [x.slug for x in self.allowed_systems] if self.allowed_systems else None
        }

    @classmethod
    def from_dict(cls, data):
        from idm.core.models import System
        from idm.users.models import User

        allowed_systems = System.objects.filter(slug__in=data['allowed_systems']) if data['allowed_systems'] else None
        impersonated = User.objects.get(username=data['impersonated']) if data['impersonated'] else None
        impersonator = User.objects.get(username=data['impersonator']) if data['impersonator'] else None

        return cls(
            impersonated=impersonated,
            impersonator=impersonator,
            allowed_systems=allowed_systems,
        )


def requesterify(requester_or_user):
    from idm.users.models import User
    if isinstance(requester_or_user, Requester):
        return requester_or_user

    if isinstance(requester_or_user, User) or requester_or_user is None:
        return Requester(impersonated=requester_or_user, impersonator=None)

    raise TypeError('Wrong object passed to requesterify: %s' % requester_or_user)
