# -*- coding: utf-8 -*-
'''
Created on Jun 13, 2013

@author: ymh
'''
from core.models import (Thesaurus, Term, TERM_URL_STATUS_CHOICES_TRANS, 
    TERM_WK_LINK_SEMANTIC_LEVEL_CHOICES_TRANS)
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import (UserChangeForm as AuthUserChangeForm, 
    UserCreationForm as AuthUserCreationForm)
from django.forms import Form, fields, ModelChoiceField, ValidationError
from django.forms.fields import ChoiceField
from django.forms.util import flatatt
from django.forms.widgets import (Widget, Select, 
    NullBooleanSelect as DjangoNullBooleanSelect)
from django.utils import formats
from django.utils.encoding import force_text
from django.utils.html import format_html, escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _, ugettext_lazy
from jocondelab import settings
import json

User = get_user_model()

class ThesaurusTreeWidget(Widget):
    
    def _format_value(self, value):
        if self.is_localized:
            return formats.localize_input(value)
        return value

    def render(self, name, value, attrs=None):
        term = None
        if isinstance(value, Term):
            term = value
        elif value and isinstance(value, (int, basestring)):
            terms = list(Term.objects.filter(id=int(value)))  # @UndefinedVariable
            if terms:
                term = terms[0]

        final_attrs = self.build_attrs(attrs, type="hidden", name=name)
        if term is not None:
            # Only add the 'value' attribute if a value is non-empty.
            final_attrs['value'] = force_text(self._format_value(term.id))
            final_attrs['data-term_tree_node'] = mark_safe(json.dumps({'id': term.id, 'label': escape(term.label)}).replace("\"", "'"));
        input_res = format_html('<input{0} />', flatatt(final_attrs))
                
        if term is not None:
            dialog_text = term.label
        else:
            dialog_text = _("Open Dialog")
            
        dialog_res = "<div id=\"dialog-link-container\" class=\"ui-state-default ui-corner-all\"><a href=\"#\" id=\"dialog-link\" title=\"%s\">%s</a><span class=\"ui-icon ui-icon-closethick\" id=\"dialog-deselect\"></span></div>" % (_("Open Dialog"),dialog_text)
        
        return input_res + dialog_res

class NullBooleanSelect(DjangoNullBooleanSelect):
    """
    A Select Widget intended to be used with NullBooleanField.
    """
    def __init__(self, attrs=None):
        choices = (('1', ('---')),
                   ('2', ugettext_lazy('yes')),
                   ('3', ugettext_lazy('no')))
        Select.__init__(self, attrs, choices)


class ValidateTermForm(Form):
    term_id = fields.IntegerField(required=True)
    validation_val = fields.BooleanField(required=False)

class WikipediaEditionForm(Form):
    term_id = fields.IntegerField(required=True)
    wikipedia_edition = fields.BooleanField(required=False)
    
class ModifyWpLinkForm(Form):
    term_id = fields.IntegerField(required=True)
    label = fields.CharField(required=True, min_length=1)
    wp_lang = fields.ChoiceField(label=_('Wikipedia version'), required=False, choices=tuple([(k,k) for k in settings.WIKIPEDIA_URLS]))

class LinkSemanticLevelForm(Form):
    term_id = fields.IntegerField(required=True)
    link_semantic_level = fields.IntegerField(required=True)

class RemoveWpLinkForm(Form):
    term_id = fields.IntegerField(required=True)
         
class TermFilterForm(Form):
    thesaurus = ModelChoiceField(label=_("thesaurus"), required=False, queryset=Thesaurus.objects.all().order_by('label'))
    thesaurus_tree = ModelChoiceField(label=_("thesaurus tree"), queryset=Term.objects.all(), required=False, widget=ThesaurusTreeWidget)  # @UndefinedVariable
    label = fields.CharField(label=_("label"), required=False)
    link_status = fields.TypedChoiceField(label=_("link_status"), required=False, empty_value=-1, coerce=int, choices=tuple([(-1,'---------')]+[(v, l) for v,l in TERM_URL_STATUS_CHOICES_TRANS]))
    link_semantic_level = fields.TypedChoiceField(label=_("link_semantic_level"), required=False, empty_value=0, coerce=int, choices=TERM_WK_LINK_SEMANTIC_LEVEL_CHOICES_TRANS)
    wikipedia_edition = fields.NullBooleanField(label=_("wikipedia_edition"), required=False, widget=NullBooleanSelect)
    validated = fields.NullBooleanField(label=_("validated"), required=False, widget=NullBooleanSelect)
    order_by = fields.ChoiceField(label=_("order_by"), required=False, choices=(('normalized_label',_('label')),('nb_notice',_('nb notice')),('level',_('level')),('lft', _('order_lft'))))
    order_dir = fields.ChoiceField(label=_("order_dir"), required=False, choices=(('asc',_('asc')), ('desc',_('desc'))))
    
    def __init__(self, *args, **kwargs):
        super(TermFilterForm, self).__init__(*args, **kwargs)
        if self.data.get('order_by', 'normalized_label') == 'lft':        
            self.fields['order_dir'].widget.attrs['disabled'] = 'disabled'
            
    def clean(self):
        fields_not_empty = any([v for k,v in self.cleaned_data.items() if k not in ('thesaurus','thesaurus_tree', 'link_status', 'order_by', 'order_dir')] + [self.cleaned_data.get('link_status', -1) >= 0])
        self.can_display_level = (not fields_not_empty) and (self.cleaned_data.get('thesaurus',None) is not None) and (self.cleaned_data.get('order_by','normalized_label') == 'lft')
        self.selected_thesaurus = self.cleaned_data.get('thesaurus', None) 
        return super(TermFilterForm, self).clean()
        
    
    def get_filter_qs(self, base_qs=None):
        qs = base_qs
        
        if qs is None:
            qs = Term.objects.all()  # @UndefinedVariable
                
        thes = self.cleaned_data.get('thesaurus',None)
        if thes:
            qs = qs.filter(thesaurus=thes)

        thes_tree = self.cleaned_data.get('thesaurus_tree',None)
        if thes_tree:
            qs = qs & thes_tree.get_descendants()  # @UndefinedVariable

        lk_status = self.cleaned_data.get('link_status',-1)
        if lk_status>=0:
            qs = qs.filter(url_status=lk_status)
            
        lk_semantic_level = self.cleaned_data.get('link_semantic_level', 0)
        if lk_semantic_level:
            qs = qs.filter(link_semantic_level=lk_semantic_level)            
            
        validated = self.cleaned_data.get('validated', None)
        if validated is not None:
            qs = qs.filter(validated=validated)
            
        wikipedia_edition = self.cleaned_data.get('wikipedia_edition', None)
        if wikipedia_edition is not None:
            qs = qs.filter(wikipedia_edition=wikipedia_edition)
            
        label_regexp = self.cleaned_data.get('label', None)
        if label_regexp:
            qs = qs.filter(label__iregex=label_regexp)
        
        order_by = self.cleaned_data.get('order_by', 'normalized_label') or 'normalized_label'
        order_dir = self.cleaned_data.get('order_dir', 'asc') or 'asc'
        if order_dir == 'desc':
            dir_order_by = "-"+order_by
        else:
            dir_order_by = order_by
        if order_by == "normalized_label" or order_by == "label":
            order_by = [dir_order_by, 'nb_notice', 'id']
        elif order_by == "lft":
            order_by = ['tree_id', order_by, 'nb_notice', 'id']
        else:
            order_by = [dir_order_by, 'normalized_label', 'id']
        qs = qs.order_by(*order_by)
        
        return qs
    
class UserCreationform(AuthUserCreationForm):
    class Meta:
        model = User
        
    def clean_username(self):
        # Since User.username is unique, this check is redundant,
        # but it sets a nicer error message than the ORM. See #13147.
        username = self.cleaned_data["username"]
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            return username
        raise ValidationError(self.error_messages['duplicate_username'])    
    

class UserChangeForm(AuthUserChangeForm):
    language = ChoiceField(label=_("language"), choices=[(k,_(v)) for k,v in settings.LANGUAGES], initial=settings.LANGUAGE_CODE[:2])
    class Meta:
        model = User
