from django.contrib.auth.models import User, Group
from django.contrib.auth import authenticate
from django.contrib.sites.models import Site
from django.template import RequestContext, Context, loader
from django.core import validators
from pycon.core import safe_utf8_encode, safe_ascii_encode
from django.utils.encoding import force_unicode, smart_str
from django import forms
from models import *
from newforms import ProposalForm
from changelog import *

class EditCoAuthorsForm(Proposal.ChangeManipulator):
    def __init__(self, user, proposal, **kwdargs):
        self.user = user
        self.proposal = proposal
        kwdargs['follow'] = dict( (field.field_name, False)
             for field in Proposal.ChangeManipulator(proposal.id).fields
             if field.field_name != 'coauthors' )
        super(EditCoAuthorsForm, self).__init__(proposal.id, **kwdargs)
        for field in self.fields:
            if field.field_name == 'coauthors':
                filt = [ rev.id for rev in proposal.reviewers.all() ]
                filt.append(proposal.submitter_id)
                field.choices = [ (id, val) for id, val in field.choices
                                  if id not in filt ]
                field.validator_list = [self.does_not_contain_submitter,
                                        self.does_not_contain_reviewers]
                break
    def does_not_contain_submitter(self, field_data, all_data):
        if str(self.proposal.submitter_id) in field_data:
            raise validators.ValidationError, (
                "The primary author '%s' can not be listed as a co-author." %
                    unicode(self.proposal.submitter))
    def does_not_contain_reviewers(self, field_data, all_data):
        revd = dict((str(rev.id), rev) for rev in self.proposal.reviewers.all())
        rids = set(revd)&set(field_data)
        if rids:
            reviewers = ', '.join(str(revd[rid]) for rid in rids)
            raise validators.ValidationError, (
                "The following people have been assigned as a reviewer of this "
                "proposal and can not be assigned as a Co-Author. "
                "Please contact the reviewer(s) and/or a convention organizer "
                "to resolve this issue: " + reviewers)
    def save(self, data):
        old = set(ent['id'] for ent in self.proposal.coauthors.values('id'))
        prop = super(EditCoAuthorsForm, self).save(data)
        new = set(ent['id'] for ent in prop.coauthors.values('id'))
        added   = [ "Author #" + str(id) for id in new - old ]
        removed = [ "Author #" + str(id) for id in old - new ]
        log_coauthor_edit(self.user, prop, added, removed)
        return prop

class NewReviewForm(Review.AddManipulator):
    def __init__(self, user, prop, **kwdargs):
        self.prop = prop
        self.user = user
        kwdargs['follow'] = { 'updated': False }
        super(NewReviewForm, self).__init__(**kwdargs)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'proposal':
                break
        self.fields.pop(ind)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'reviewer':
                break
        self.fields.pop(ind)
    def save(self, new_data):
        new_data['proposal'] = self.prop.id
        new_data['reviewer'] = self.user.id
        assigning = self.user not in self.prop.reviewers.all()
        review = super(NewReviewForm, self).save(new_data)
        log_review(self.user, self.prop, review, assign_voter=assigning)
        return review

class EditReviewForm(Review.ChangeManipulator):
    def __init__(self, user, prop, rev, **kwdargs):
        self.user = user
        self.prop = prop
        self.rev = rev
        kwdargs['follow'] = { 'proposal': False, 'reviewer': False,
                              'updated': False }
        super(EditReviewForm, self).__init__(rev.id, **kwdargs)
    def save(self, new_data):
        log_change = log_review(self.user, self.prop, new_data, self.rev)
        new_rev = super(EditReviewForm, self).save(new_data)
        log_change()
        return new_rev

class NewCommentForm(Comment.AddManipulator):
    def __init__(self, prop, request, **kwdargs):
        self.prop = prop
        self.request = request
        self.user = request.user
        kwdargs['follow'] = { 'submitted': False }
        super(NewCommentForm, self).__init__(**kwdargs)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'proposal':
                break
        self.fields.pop(ind)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'commenter':
                break
        self.fields.pop(ind)
    def save(self, new_data):
        new_data['proposal'] = self.prop.id
        new_data['commenter'] = self.user.id
        comment = super(NewCommentForm, self).save(new_data)
        log_comment(self.user, self.prop, comment)
        emails = []
        t = loader.get_template("propmgr/email/proposal_comment.txt")
        users = []
        users.append(comment.proposal.submitter)
        users.extend(comment.proposal.coauthors.all())
        users.extend(comment.proposal.reviewers.all())
        comments = self.prop.comment_set.exclude(commenter__in=[u.id for u in users])
        seen = set()
        users.extend(c.commenter for c in comments
            if not (c.commenter.id in seen or seen.add(c.commenter.id)))
        for user in users:
            if user == self.user:
                continue
            c = {
                'mailto': user,
                'email': user.email,
                'comment': comment,
                'prop_and_user': (comment.proposal, user)
            }
            message = t.render(RequestContext(self.request, c))
            subject = settings.CONFERENCE_NAME
            subject += ' New Talk Proposal Comment ('
            subject += "%d. " % comment.proposal.id
            subject += smart_str(comment.proposal.title)
            subject += ')'
            #from pycon.core.mail import SafeMIMEText
            #x = SafeMIMEText("testing")
            #x.Subject = subject ## hack test
            emails.append({
                'subject': subject,
                'body': message,
                'from_email': settings.PROPMGR_FROM_EMAIL,
                'replyto_email': settings.PROPMGR_REPLYTO_EMAIL,
                'to': [user.email]})
        from pycon.core import mail
        mail.send_mass_mail(emails)
        return comment

class AttachFileForm(AttachedFile.AddManipulator):
    def __init__(self, user, prop, **kwdargs):
        self.prop = prop
        self.user = user
        kwdargs['follow'] = { 'submitted': False,
                              'published': False }
        super(AttachFileForm, self).__init__(**kwdargs)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'proposal':
                break
        self.fields.pop(ind)
        for ind, field in enumerate(self.fields):
            if field.field_name == 'submitter':
                break
        self.fields.pop(ind)
    def save(self, new_data):
        new_data['proposal'] = self.prop.id
        new_data['submitter'] = self.user.id
        atfile = super(AttachFileForm, self).save(new_data)
        log_attach_file(self.user, self.prop, atfile)
        return atfile
