"""Proposal System USer Permissions Extensions
"""
from pycon.core import *
from templatetags.propmeth import register
from django.contrib.auth.models import User, AnonymousUser, Group

@register.filter
def has_perm(user, perm):
    return user.has_perm(perm)
    
class UserPermissions:
    @staticmethod
    @bind_prop_to_class(User)
    @bind_prop_to_class(AnonymousUser)
    def can_view_proposal_listing(user):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user.is_staff: return True
        return (user.has_perm('propmgr.can_view_all_proposals') or
                user.has_perm('propmgr.can_view_proposal_listing'))

    @staticmethod
    @bind_prop_to_class(User)
    @bind_prop_to_class(AnonymousUser)
    def can_view_all_proposals(user):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user.is_staff: return True
        return user.has_perm('propmgr.can_view_all_proposals')

    @staticmethod
    @bind_prop_to_class(User)
    @bind_prop_to_class(AnonymousUser)
    def can_view_proposal_stats(user):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user.is_staff: return True
        return user.has_perm('propmgr.can_view_proposal_stats')

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_proposal(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user.is_staff: return True
        if user.has_perm('propmgr.can_view_all_proposals'):
            return True
        if user == proposal.submitter: return True
        if user in proposal.coauthors.all(): return True
        if user in proposal.reviewers.all(): return True
        return False

    @staticmethod
    @bind_prop_to_class(User)
    @bind_prop_to_class(AnonymousUser)
    def can_add_proposal(user):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        return True

    @staticmethod
    @bind_prop_to_class(User)
    @bind_prop_to_class(AnonymousUser)
    def can_edit_proposal_in_admin(user):
        return user.is_staff and user.has_perm('propmgr.edit_proposal')

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_authors(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user == proposal.submitter: return True
        if user in proposal.coauthors.all(): return True
        if 'propmgr.can_view_all_authors_override' in user.get_all_permissions(): return True
        if user.has_perm('propmgr.add_review') or user in proposal.reviewers.all():
            return proposal.published
        if user.is_superuser: return True
        if user.has_perm('propmgr.can_view_all_proposals'):
            return True
        return False

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_reviewers(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user == proposal.submitter: return False
        if user in proposal.coauthors.all(): return False
        return True

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def protected_proposal_user_name(user, (proposal, other)):
        if (user == proposal.submitter or
            user in proposal.coauthors.all()):
            if other.can_view_authors(proposal):
                return user
            return "Author #" + str(user.id)
        if other.can_view_reviewers(proposal):
            return user
        return "Reviewer #" + str(user.id)
    
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_edit_coauthors(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user == proposal.submitter: return True
        #if user.is_staff: return True
        #if user in proposal.reviewers.all(): return True
        return False
    
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_edit_proposal(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        #if user.is_staff: return True
        if user == proposal.submitter: return True
        if user in proposal.coauthors.all(): return True
        #if user in proposal.reviewers.all(): return True
        return False
    
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_comments(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser: return True
        if user.is_staff: return True
        if user == proposal.submitter: return True
        if user in proposal.coauthors.all(): return True
        if user in proposal.reviewers.all(): return True
        if user.has_perm('propmgr.can_view_all_comments'): return True
        return False

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_add_comment(user, proposal):
        return user.can_view_comments(proposal)
        
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_reviews(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user.is_superuser or user.is_staff or user.has_perm('propmgr.can_view_all_reviews'):
            if not proposal.published:
                if user == proposal.submitter: return False
                if user in proposal.coauthors.all(): return False
            return True
        if user in proposal.reviewers.all(): return True
        if proposal.published:
            if user == proposal.submitter: return True
            if user in proposal.coauthors.all(): return True
    
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_add_review(user, proposal):
        #if user in proposal.reviewers.all():
        #    return proposal.review_set.filter(reviewer=user).count() == 0
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if user == proposal.submitter: return False
        if user in proposal.coauthors.all(): return False
        if not user.has_perm('propmgr.add_review'): return False
        return proposal.review_set.filter(reviewer=user).count() == 0

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_opt_out_review(user, proposal):
        if not user in proposal.reviewers.all(): return False
        return proposal.review_set.filter(reviewer=user).count() == 0
        
    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_edit_review(user, review):
        if user == review.reviewer:
            return True
        return False
    
