from __future__ import absolute_import
from irods.models import User, Group, UserAuth
from irods.meta import iRODSMetaCollection
from irods.exception import NoResultFound

_Not_Defined = ()

class Bad_password_change_parameter(Exception): pass

class iRODSUser(object):

    def remove_quota(self, resource = 'total'):
        self.manager.remove_quota(self.name, resource = resource)

    # TODO: remove this in branch 2.x (#482)
    def set_quota(self, amount, resource = 'total'):
        self.manager.set_quota(self.name, amount, resource = resource)

    def __init__(self, manager, result=None):
        self.manager = manager
        if result:
            self.id = result[User.id]
            self.name = result[User.name]
            self.type = result[User.type]
            self.zone = result[User.zone]
            self._comment = result.get(User.comment, _Not_Defined)  # these not needed in results for object ident,
            self._info = result.get(User.info, _Not_Defined)        # so we fetch lazily via a property
        self._meta = None

    @property
    def comment(self):
        if self._comment == _Not_Defined:
            query = self.manager.sess.query(User.id,User.comment).filter(User.id == self.id)
            self._comment = query.one()[User.comment]
        return self._comment

    @property
    def info(self):
        if self._info == _Not_Defined:
            query = self.manager.sess.query(User.id,User.info).filter(User.id == self.id)
            self._info = query.one()[User.info]
        return self._info

    @property
    def dn(self):
        query = self.manager.sess.query(UserAuth.user_dn).filter(UserAuth.user_id == self.id)
        return [res[UserAuth.user_dn] for res in query]

    @property
    def metadata(self):
        if not self._meta:
            self._meta = iRODSMetaCollection(
                 self.manager.sess.metadata, User, self.name)
        return self._meta

    def modify_password(self, old_value, new_value, modify_irods_authentication_file = False):
        self.manager.modify_password(old_value,
                                     new_value,
                                     modify_irods_authentication_file = modify_irods_authentication_file)

    def modify(self, *args, **kwargs):
        self.manager.modify(self.name, *args, **kwargs)

    def __repr__(self):
        return "<iRODSUser {id} {name} {type} {zone}>".format(**vars(self))

    def remove(self):
        self.manager.remove(self.name, self.zone, _object = self)

    def temp_password(self):
        return self.manager.temp_password_for_user(self.name)


class iRODSGroup(object):

    type = "rodsgroup"

    def remove_quota(self, resource = 'total'):
        self.set_quota(amount = 0, resource = resource)

    def set_quota(self, amount, resource = 'total'):
        self.manager.set_quota(self.name, amount, resource = resource)

    def __init__(self, manager, result=None):
        self.manager = manager
        if result:
            self.id = result[Group.id]
            self.name = result[Group.name]
        self._meta = None

    def __repr__(self):
        return "<iRODSGroup {id} {name}>".format(**vars(self))

    def remove(self):
        self.manager.remove(self.name, _object = self)

    @property
    def members(self):
        return self.manager.getmembers(self.name)

    @property
    def metadata(self):
        if not self._meta:
            self._meta = iRODSMetaCollection(
                 self.manager.sess.metadata, User, self.name)
        return self._meta

    def addmember(self, user_name, user_zone=""):
        self.manager.addmember(self.name, user_name, user_zone)

    def removemember(self, user_name, user_zone=""):
        self.manager.removemember(self.name, user_name, user_zone)

    def hasmember(self, user_name):
        member_names = [user.name for user in self.members]
        return user_name in member_names

# The iRODSUserGroup is now renamed iRODSGroup, but we'll keep the deprecated name around for now.
iRODSUserGroup = iRODSGroup
