"""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 proposal.coauthors.filter(pk=user.id).count(): return True
        if proposal.reviewers.filter(pk=user.id).count(): 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 user.has_perm('propmgr.can_view_all_authors_override'): return True
        if (user.has_perm('propmgr.add_review') or
            proposal.reviewers.filter(pk=user.id).count()):
            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_proposal_status(user, proposal):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if proposal.published: return True
        if proposal.status in ['R', 'C', 'W']: return True
        if user == proposal.submitter: return False
        if proposal.coauthors.filter(pk=user.id).count(): return False
        return True

    @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 proposal.coauthors.filter(pk=user.id).count(): 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
            proposal.coauthors.filter(pk=user.id).count()):
            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 proposal.coauthors.filter(pk=user.id).count(): 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 proposal.coauthors.filter(pk=user.id).count(): return True
        if proposal.reviewers.filter(pk=user.id).count(): 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 proposal.coauthors.filter(pk=user.id).count(): return False
            return True
        if proposal.reviewers.filter(pk=user.id).count(): return True
        if proposal.published:
            if user == proposal.submitter: return True
            if proposal.coauthors.filter(pk=user.id).count(): 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 proposal.coauthors.filter(pk=user.id).count(): 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 proposal.reviewers.filter(pk=user.id).count(): 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

    @staticmethod
    @bind_meth_to_class(User)
    @bind_meth_to_class(AnonymousUser)
    @register.filter
    def can_view_proposal_history(user, proposal):
        return user.can_view_proposal(proposal)

    @staticmethod
    @register.filter
    def history_change_can_be_viewed(change, (proposal, user)):
        if user.is_anonymous(): return False
        if not user.is_active: return False
        if change.model == 'proposal' and change.action == 'edit': return True
        if change.user == user: return True
        if user == proposal.submitter: return False
        if proposal.coauthors.filter(pk=user.id).count():
            return proposal.coauthors.filter(pk=change.user.id).count()
        return user.has_perm('propmgr.add_review')
