"""
Brochures forms..
"""
from django import forms
from django.conf import settings
from django.core.validators import validate_email
from models import Pdf, Section
from rldjango.common.middleware import getCurrentUser
from utils import get_dependant_sections,get_sections_string

class SectionAdminInlineForm(forms.ModelForm):
    """
    Exclude source from form.
    """
    abstract = forms.BooleanField(
        label="Abstract",
        widget=forms.CheckboxInput(attrs={'class': 'abstract_section'}),
        required=False,
        )
    start = forms.IntegerField(
        label="Start",
        widget=forms.TextInput(attrs={'class': 'page_range'}),
        )
    end = forms.IntegerField(
        label="End",
        widget=forms.TextInput(attrs={'class': 'page_range'}),
        )
    
    class Meta: # pylint: disable-msg=W0232,C0111,R0903
        model = Section
        exclude = ('source', 'pages', 'updated', 'pages_updated')


class CreateForm(forms.forms.Form):
    """
    Dynamic form for creating brochures.
    """
    
    def __init__(self, *args, **kwargs): # pylint: disable-msg=W0231
        """
        Form can be generated from pdf or groups.
        """
        group = kwargs.pop('group', None)
        pdf = kwargs.pop('pdf', None)
        if not pdf: # Backstop for use when this form is in a formset
            pdf = kwargs.pop('initial', None)
        selected_sections = kwargs.pop('selected_sections', None)
        expanded_sections = kwargs.pop('expanded_sections', None)
        
        super(CreateForm, self).__init__(*args, **kwargs)

        if group:
            raise NotImplementedError
        elif pdf:
            self.pdf = pdf
            es=get_sections_string(expanded_sections,pdf.id)
            sections = pdf.section_set.all().order_by('order') # pylint: disable-msg=E1101
        else:
            raise KeyError('You have to provide group or pdf.')

        section_template = lambda : dict(
                fields=[],
                mandatory=False,
                hidden=False,
                name=None,
                field=None,
                )

        self.field_groups = []
        
        actual_group = section_template()
        selected_sections=get_dependant_sections(selected_sections, pdf_id=pdf.id)
        selected_section_ids=[]
        for i in selected_sections:
            selected_section_ids.append(i.id)
        
        for section in sections:
            name = 'section_%d' % section.id
            if section.abstract:
                #add a 'group header' section
                actual_group = section_template()
                actual_group['name'] = section.name
                actual_group['mandatory'] = section.mandatory
                actual_group['hidden'] = section.hidden
                if section in es:
                    actual_group['expanded'] = True
                self.field_groups.append(actual_group)
                field = forms.BooleanField(
                    required=False,
                    label=section.name,
                    initial=True)
                self.fields[name] = field
                actual_group['field'] = self[name]
                
            else:
                #add a normal section
                if (section.id in selected_section_ids):
                    selected = True
                else:
                    selected = actual_group['mandatory']
                field = forms.BooleanField(
                    required=False,
                    label=section.name,
                    initial=selected)
                self.fields[name] = field
                actual_group['fields'].append(self[name])
            
    def full_clean(self):
        """
        Populate self.cleaned_data with real section ids.
        """
        super(CreateForm, self).full_clean()
        cleaned_data = self.cleaned_data.copy()
        self.cleaned_data = {}
        for field_name, data in cleaned_data.iteritems():
            self.cleaned_data[int(field_name.replace('section_', ''))] = data
            

class ReCaptcha(forms.widgets.Widget):
    """
    ReCaptcha widget..
    """
    recaptcha_challenge_name = 'recaptcha_challenge_field'
    recaptcha_response_name = 'recaptcha_response_field'
    
    def render(self, name, value, attrs=None):
        """
        Returns recapthca html..
        """
        from recaptcha.client import captcha
        from django.utils.safestring import mark_safe
        return mark_safe(u'%s' % captcha.displayhtml(settings.RECAPTCHA_PUBLIC_KEY))
    
    def value_from_datadict(self, data, files, name):
        return [data.get(self.recaptcha_challenge_name, None), 
                data.get(self.recaptcha_response_name, None)]

class ReCaptchaField(forms.CharField):
    """
    We need just modify to_python method.
    """

    def to_python(self, value):
        "Return [recaptcha_challenge_value, recaptcha_response_value]."
        if value:
            return value
        else:
            return []
            
class MultiEmailField(forms.Field):
    """
    This field accept multiple comma separated adresses.
    """
    def to_python(self, value):
        "Normalize data to a list of strings."

        # Return an empty list if no input was given.
        if not value:
            return []
        return value.split(',')

    def validate(self, value):
        "Check if value consists only of valid emails."

        # Use the parent's handling of required fields, etc.
        super(MultiEmailField, self).validate(value)

        for email in value:
            validate_email(email.strip())


def makeDownloadFormActionField(display='123',initial='download'):
    choices=[]
    type=1
    v='visible'
    if '1' in display or 'download' in display:
        choices.append(('download','Download PDF'))
    if '2' in display or 'flip_book' in display:
        choices.append(('flip_book', ('View PDF as flip book (Requires Adobe Flash.'
                               ' Users of Apple mobile devices - e.g. iPhones'
                               ' or iPads - should choose the Download or Email'
                               ' options.)')))
    if '3' in display or 'email' in display:
        choices.append(('email','Email PDF to yourself or a friend'))
    if len(choices)<=1:
        if len(choices)==0:
            return makeDownloadFormActionField('123',initial)
        label = ' '
        v='hidden'
    else:
        label="Please choose one of the following actions:"

    if '3' in initial: initial='email'
    if '2' in initial: initial='flip_book'

    if initial not in [c[0] for c in choices]:
        initial = choices[0][0]
    return forms.CharField(
        label=label,
        widget=forms.RadioSelect(choices=tuple(choices), attrs={'style':('visibility:%s' % v)}),
        initial=initial,
        required=True,
        )

class DownloadForm(forms.forms.Form):
    """
    Download form..
    """
    action = makeDownloadFormActionField()
    recaptcha = ReCaptchaField(
        label="3. Verify and send",
        widget=ReCaptcha(),
        required=False,
        )

    email_to = MultiEmailField(
        label="1. Enter email address:",
        required=False,
        )

    email_from = forms.CharField(
        label="2. Enter your name (optional):",
        required=False,
        )

    
    email_body = forms.CharField(
        label='Message to include in the body of the email: (optional):',
        widget=forms.Textarea(),
        required=False,
        )
        
    def full_clean(self):
        """
        Check recaptcha if emailing to friend.
        """
        super(DownloadForm, self).full_clean()
        if getattr(self, 'cleaned_data', None):
            cleaned_data = self.cleaned_data.copy()
            from django.utils.encoding import smart_unicode
            from recaptcha.client import captcha
            if cleaned_data['action'] == 'email':
                if cleaned_data['email_to']:
                    #are they logged in?  if so, don't check captcha
                    user = getCurrentUser()
                    if user and user.is_authenticated():
                        #we have a logged in user; less tests needed.
                        pass
                    else:
                        # check captcha
                        values = cleaned_data['recaptcha']
                        recaptcha_challenge_value = smart_unicode(values[0])
                        recaptcha_response_value = smart_unicode(values[1])
                        check_captcha = captcha.submit(
                            recaptcha_challenge_value, 
                            recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {})

                        if not check_captcha.is_valid:
                            delattr(self, 'cleaned_data')
                            self._errors['recaptcha'] = 'Invalid captcha'
                else:
                    delattr(self, 'cleaned_data')
                    self._errors['email_to'] = 'This field is required.'

