#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import logging
import warnings

from pylons import app_globals as g, tmpl_context as c
from formencode import validators as fev
import formencode
import ew as ew_core
import ew.jinja2_ew as ew
from pytz import common_timezones, country_timezones, country_names
from paste.deploy.converters import aslist, asint
import tg

from allura.lib import validators as V
from allura.lib import helpers as h
from allura.lib import plugin
from allura.lib.widgets import form_fields as ffw
from allura.lib import exceptions as forge_exc
from allura import model as M


log = logging.getLogger(__name__)

weekdays = ['Monday', 'Tuesday', 'Wednesday',
            'Thursday', 'Friday', 'Saturday', 'Sunday']


class _HTMLExplanation(ew.InputField):
    template = ew.Snippet(
        '''<label class="grid-4">&nbsp;</label>
           <div class="grid-14" style="margin:2px;">{{widget.text}}</div>
        ''',
        'jinja2')


class NeighborhoodProjectShortNameValidator(fev.FancyValidator):

    def _validate_shortname(self, shortname, neighborhood, state):
        if not h.re_project_name.match(shortname):
            raise forge_exc.ProjectShortnameInvalid(
                'Please use only letters, numbers, and dashes 3-15 characters long.',
                shortname, state)

    def _validate_allowed(self, shortname, neighborhood, state):
        p = M.Project.query.get(
            shortname=shortname, neighborhood_id=neighborhood._id)
        if p:
            raise forge_exc.ProjectConflict(
                'This project name is taken.',
                shortname, state)

    def to_python(self, value, state=None, check_allowed=True, neighborhood=None):
        """
        Validate a project shortname.

        If check_allowed is False, the shortname will only be checked for
        correctness.  Otherwise, it will be rejected if already in use or
        otherwise disallowed.
        """
        if neighborhood is None:
            neighborhood = M.Neighborhood.query.get(
                name=state.full_dict['neighborhood'])
        value = h.really_unicode(value or '').encode('utf-8').lower()
        self._validate_shortname(value, neighborhood, state)
        if check_allowed:
            self._validate_allowed(value, neighborhood, state)
        return value


class ForgeForm(ew.SimpleForm):
    antispam = False
    template = 'jinja:allura:templates/widgets/forge_form.html'
    defaults = dict(
        ew.SimpleForm.defaults,
        submit_text='Save',
        style='standard',
        method='post',
        enctype=None,
        target=None)

    def display_label(self, field, label_text=None):
        ctx = super(ForgeForm, self).context_for(field)
        label_text = (
            label_text
            or ctx.get('label')
            or getattr(field, 'label', None)
            or ctx['name'])
        html = '<label for="%s">%s</label>' % (
            ctx['id'], label_text)
        return h.html.literal(html)

    def context_for(self, field):
        ctx = super(ForgeForm, self).context_for(field)
        if self.antispam:
            ctx['rendered_name'] = g.antispam.enc(ctx['name'])
        return ctx

    def display_field(self, field, ignore_errors=False):
        ctx = self.context_for(field)
        display = field.display(**ctx)
        if ctx['errors'] and field.show_errors and not ignore_errors:
            display = "%s<div class='error'>%s</div>" % (display,
                                                         ctx['errors'])
        return h.html.literal(display)

    def display_field_by_idx(self, idx, ignore_errors=False):
        warnings.warn(
            'ForgeForm.display_field_by_idx is deprecated; use '
            'ForgeForm.display_field() instead', DeprecationWarning)
        field = self.fields[idx]
        ctx = self.context_for(field)
        display = field.display(**ctx)
        if ctx['errors'] and field.show_errors and not ignore_errors:
            display = "%s<div class='error'>%s</div>" % (display,
                                                         ctx['errors'])
        return display


class PasswordChangeBase(ForgeForm):

    @property
    def fields(self):
        return [
            ew.PasswordField(
                name='pw',
                label='New Password',
                validator=fev.UnicodeString(
                    not_empty=True,
                    min=asint(tg.config.get('auth.min_password_len', 6)),
                    max=asint(tg.config.get('auth.max_password_len', 30)))),
            ew.PasswordField(
                name='pw2',
                label='New Password (again)',
                validator=fev.UnicodeString(not_empty=True)),
        ]

    @ew_core.core.validator
    def to_python(self, value, state):
        d = super(PasswordChangeBase, self).to_python(value, state)
        if d['pw'] != d['pw2']:
            raise formencode.Invalid('Passwords must match', value, state)
        return d


class PasswordChangeForm(PasswordChangeBase):

    @property
    def fields(self):
        return [
            ew.PasswordField(
                name='oldpw',
                label='Old Password',
                validator=fev.UnicodeString(not_empty=True)),
            ew.PasswordField(
                name='pw',
                label='New Password',
                validator=fev.UnicodeString(
                    not_empty=True,
                    min=asint(tg.config.get('auth.min_password_len', 6)),
                    max=asint(tg.config.get('auth.max_password_len', 30)))),
            ew.PasswordField(
                name='pw2',
                label='New Password (again)',
                validator=fev.UnicodeString(not_empty=True)),
        ]


class PersonalDataForm(ForgeForm):

    class fields(ew_core.NameList):
        sex = ew.SingleSelectField(
            label='Gender',
            options=[ew.Option(py_value=v, label=v, selected=False)
                     for v in ['Male', 'Female', 'Unknown', 'Other']],
            validator=formencode.All(
                V.OneOfValidator(['Male', 'Female', 'Unknown', 'Other']),
                fev.UnicodeString(not_empty=True)))
        birthdate = ew.TextField(
            label='Birth date',
            validator=V.DateValidator(),
            attrs=dict(value=None))
        exp = _HTMLExplanation(
            text="Use the format DD/MM/YYYY",
            show_errors=False)
        country = ew.SingleSelectField(
            label='Country of residence',
            validator=V.MapValidator(country_names, not_empty=False),
            options=[
                ew.Option(
                    py_value=" ", label=" -- Unknown -- ", selected=False)] +
            [ew.Option(py_value=c, label=n, selected=False)
             for c, n in sorted(country_names.items(),
                                key=lambda (k, v):v)],
            attrs={'onchange': 'selectTimezone(this.value)'})
        city = ew.TextField(
            label='City of residence',
            attrs=dict(value=None),
            validator=fev.UnicodeString(not_empty=False))
        timezone = ew.SingleSelectField(
            label='Timezone',
            attrs={'id': 'tz'},
            validator=V.OneOfValidator(common_timezones, not_empty=False),
            options=[
                ew.Option(
                    py_value=" ",
                    label=" -- Unknown -- ")] +
            [ew.Option(py_value=n, label=n)
                  for n in sorted(common_timezones)])

    def display(self, **kw):
        user = kw.get('user')

        for opt in self.fields['sex'].options:
            if opt.label == user.sex:
                opt.selected = True
            else:
                opt.selected = False

        if user.get_pref('birthdate'):
            self.fields['birthdate'].attrs['value'] = \
                user.get_pref('birthdate').strftime('%d/%m/%Y')
        else:
            self.fields['birthdate'].attrs['value'] = ''

        for opt in self.fields['country'].options:
            if opt.label == user.localization.country:
                opt.selected = True
            elif opt.py_value == " " and user.localization.country is None:
                opt.selected = True
            else:
                opt.selected = False

        if user.localization.city:
            self.fields['city'].attrs['value'] = user.localization.city
        else:
            self.fields['city'].attrs['value'] = ''

        for opt in self.fields['timezone'].options:
            if opt.label == user.timezone:
                opt.selected = True
            elif opt.py_value == " " and user.timezone is None:
                opt.selected = True
            else:
                opt.selected = False

        return super(ForgeForm, self).display(**kw)

    def resources(self):
        def _append(x, y):
            return x + y

        yield ew.JSScript('''
var $allTimezones = $("#tz").clone();
var $t = {};
''' +
                          reduce(_append, [
                              '$t["' + el + '"] = ' + str([name.encode('utf-8')
                                                           for name in country_timezones[el]]) + ";\n"
                              for el in country_timezones]) + '''
function selectTimezone($country){
     if($country == " "){
         $("#tz").replaceWith($allTimezones);
     }
     else{
         $("#tz option:gt(0)").remove();
         $.each($t[$country], function(index, value){
             $("#tz").append($("<option></option>").attr("value", value).text(value))
         })
     }
}''')


class AddTelNumberForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    class fields(ew_core.NameList):
        newnumber = ew.TextField(
            label='New telephone number',
            attrs={'value': ''},
            validator=fev.UnicodeString(not_empty=True))

    def display(self, **kw):
        initial_value = kw.get('initial_value', '')
        self.fields['newnumber'].attrs['value'] = initial_value
        return super(ForgeForm, self).display(**kw)


class AddWebsiteForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    class fields(ew_core.NameList):
        newwebsite = ew.TextField(
            label='New website url',
            attrs={'value': ''},
            validator=fev.URL())

    def display(self, **kw):
        initial_value = kw.get('initial_value', '')
        self.fields['newwebsite'].attrs['value'] = initial_value
        return super(ForgeForm, self).display(**kw)


class SkypeAccountForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    class fields(ew_core.NameList):
        skypeaccount = ew.TextField(
            label='Skype account',
            attrs={'value': ''},
            validator=fev.UnicodeString(not_empty=False))

    def display(self, **kw):
        initial_value = kw.get('initial_value', '')
        self.fields['skypeaccount'].attrs['value'] = initial_value
        return super(ForgeForm, self).display(**kw)


class RemoveTextValueForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        initial_value = kw.get('value', '')
        label = kw.get('label', '')
        description = kw.get('description')

        self.fields = [
            ew.RowField(
                show_errors=False,
                fields=[
                    ffw.DisplayOnlyField(text=label),
                    ffw.DisplayOnlyField(
                        name='oldvalue',
                        label=initial_value,
                        attrs={'value': initial_value},
                        show_errors=False),
                    ew.SubmitButton(
                        show_label=False,
                        attrs={'value': 'Remove'},
                        show_errors=False)])]
        if description:
            self.fields.append(
                _HTMLExplanation(
                    text=description,
                    show_errors=False))
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveTextValueForm, self).to_python(kw, state)
        d["oldvalue"] = kw.get('oldvalue', '')
        return d


class AddSocialNetworkForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    @property
    def fields(self):
        socialnetworks = aslist(tg.config.get('socialnetworks',
                                              ['Facebook', 'Linkedin', 'Twitter', 'Google+']),
                                ',')
        return [
            ew.SingleSelectField(
                name='socialnetwork',
                label='Social network',
                validator=fev.UnicodeString(not_empty=True),
                options=[ew.Option(py_value=name, label=name)
                         for name in socialnetworks]),
            ew.TextField(
                name='accounturl',
                label='Account url',
                validator=fev.UnicodeString(not_empty=True))
        ]


class RemoveSocialNetworkForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        account = kw.get('account', '')
        socialnetwork = kw.get('socialnetwork', '')

        self.fields = [
            ew.RowField(
                show_errors=False,
                fields=[
                    ffw.DisplayOnlyField(
                        text='%s account' % socialnetwork,
                        name="socialnetwork",
                        attrs={'value': socialnetwork},
                        show_errors=False),
                    ffw.DisplayOnlyField(
                        name="account",
                        attrs={'value': account},
                        show_errors=False),
                    ew.SubmitButton(
                        show_label=False,
                        attrs={'value': 'Remove'},
                        show_errors=False)])]
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveSocialNetworkForm, self).to_python(kw, state)
        d["account"] = kw.get('account', '')
        d["socialnetwork"] = kw.get('socialnetwork', '')
        return d


class AddInactivePeriodForm(ForgeForm):

    class fields(ew_core.NameList):
        startdate = ew.TextField(
            label='Start date',
            validator=formencode.All(
                V.DateValidator(),
                fev.UnicodeString(not_empty=True)))
        enddate = ew.TextField(
            label='End date',
            validator=formencode.All(
                V.DateValidator(),
                fev.UnicodeString(not_empty=True)))

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(AddInactivePeriodForm, self).to_python(kw, state)
        if d['startdate'] > d['enddate']:
                raise formencode.Invalid(
                    'Invalid period: start date greater than end date.',
                    kw, state)
        return d


class RemoveInactivePeriodForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        startdate = kw.get('startdate')
        enddate = kw.get('enddate')

        self.fields = [
            ew.RowField(
                show_label=False,
                show_errors=False,
                fields=[
                    ffw.DisplayOnlyField(
                        name='startdate',
                        attrs={'value': startdate.strftime('%d/%m/%Y')},
                        show_errors=False),
                    ffw.DisplayOnlyField(
                        name='enddate',
                        attrs={'value': enddate.strftime('%d/%m/%Y')},
                        show_errors=False),
                    ew.SubmitButton(
                        attrs={'value': 'Remove'},
                        show_errors=False)])]
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveInactivePeriodForm, self).to_python(kw, state)
        d['startdate'] = V.convertDate(kw.get('startdate', ''))
        d['enddate'] = V.convertDate(kw.get('enddate', ''))
        return d


class AddTimeSlotForm(ForgeForm):

    class fields(ew_core.NameList):
        weekday = ew.SingleSelectField(
            label='Weekday',
            options=[ew.Option(py_value=wd, label=wd)
                     for wd in weekdays],
            validator=formencode.All(
                V.OneOfValidator(weekdays),
                fev.UnicodeString(not_empty=True)))
        starttime = ew.TextField(
            label='Start time',
            validator=formencode.All(
                V.TimeValidator(),
                fev.UnicodeString(not_empty=True)))
        endtime = ew.TextField(
            label='End time',
            validator=formencode.All(
                V.TimeValidator(),
                fev.UnicodeString(not_empty=True)))

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(AddTimeSlotForm, self).to_python(kw, state)
        if (d['starttime']['h'], d['starttime']['m']) > \
           (d['endtime']['h'], d['endtime']['m']):
                raise formencode.Invalid(
                    'Invalid period: start time greater than end time.',
                    kw, state)
        return d


class RemoveTimeSlotForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        weekday = kw.get('weekday', '')
        starttime = kw.get('starttime')
        endtime = kw.get('endtime')

        self.fields = [
            ew.RowField(
                show_errors=False,
                show_label=False,
                fields=[
                    ffw.DisplayOnlyField(
                        name='weekday',
                        attrs={'value': weekday},
                        show_errors=False),
                    ffw.DisplayOnlyField(
                        name='starttime',
                        attrs={'value': starttime.strftime('%H:%M')},
                        show_errors=False),
                    ffw.DisplayOnlyField(
                        name='endtime',
                        attrs={'value': endtime.strftime('%H:%M')},
                        show_errors=False),
                    ew.SubmitButton(
                        show_errors=False,
                        attrs={'value': 'Remove'})])]
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveTimeSlotForm, self).to_python(kw, state)
        d["weekday"] = kw.get('weekday', None)
        d['starttime'] = V.convertTime(kw.get('starttime', ''))
        d['endtime'] = V.convertTime(kw.get('endtime', ''))
        return d


class RemoveTroveCategoryForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        cat = kw.get('category')

        self.fields = [
            ew.RowField(
                show_errors=False,
                show_label=False,
                fields=[
                    ew.LinkField(
                        text=cat.fullname,
                        href="/categories/%s" % cat.shortname),
                    ew.SubmitButton(
                        show_errors=False,
                        attrs={'value': 'Remove'})],
                hidden_fields=[
                    ew.HiddenField(
                        name='categoryid',
                        attrs={'value': cat.trove_cat_id})])]
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveTroveCategoryForm, self).to_python(kw, state)
        d["categoryid"] = kw.get('categoryid')
        if d["categoryid"]:
            d["categoryid"] = int(d['categoryid'])
        return d


class AddTroveCategoryForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    class fields(ew_core.NameList):
        uppercategory_id = ew.HiddenField(
            attrs={'value': ''},
            show_errors=False)
        categoryname = ew.TextField(
            label="Category name",
            validator=fev.UnicodeString(not_empty=True))

    def display(self, **kw):
        upper_category = kw.get('uppercategory_id', 0)

        self.fields['uppercategory_id'].attrs['value'] = upper_category
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(AddTroveCategoryForm, self).to_python(kw, state)
        d["uppercategory_id"] = kw.get('uppercategory_id', 0)
        return d


class AddUserSkillForm(ForgeForm):
    defaults = dict(ForgeForm.defaults)

    class fields(ew_core.NameList):
        selected_skill = ew.HiddenField(
            attrs={'value': ''},
            show_errors=False,
            validator=fev.UnicodeString(not_empty=True))
        level = ew.SingleSelectField(
            label="Level of knowledge",
            options=[
                ew.Option(py_value="low", label="Low level"),
                ew.Option(py_value="medium", label="Medium level"),
                ew.Option(py_value="high", label="Advanced level")],
            validator=formencode.All(
                V.OneOfValidator(['low', 'medium', 'high']),
                fev.UnicodeString(not_empty=True)))
        comment = ew.TextArea(
            label="Additional comments",
            validator=fev.UnicodeString(not_empty=False),
            attrs={'rows': 5, 'cols': 30})

    def display(self, **kw):
        category = kw.get('selected_skill')

        self.fields["selected_skill"].attrs['value'] = category
        return super(ForgeForm, self).display(**kw)


class SelectSubCategoryForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text="Continue")

    class fields(ew_core.NameList):
        selected_category = ew.SingleSelectField(
            name="selected_category",
            label="Available categories",
            options=[])

    def display(self, **kw):
        categories = kw.get('categories')

        self.fields['selected_category'].options = \
            [ew.Option(py_value=el.trove_cat_id, label=el.fullname)
             for el in categories]
        self.fields['selected_category'].validator = \
            validator = formencode.All(
                V.OneOfValidator(categories),
                fev.UnicodeString(not_empty=True))
        return super(ForgeForm, self).display(**kw)


class RemoveSkillForm(ForgeForm):
    defaults = dict(ForgeForm.defaults, submit_text=None, show_errors=False)

    def display(self, **kw):
        skill = kw.get('skill')
        comment = skill['comment']
        if not comment:
            comment = "&nbsp;"

        self.fields = [
            ew.RowField(
                show_errors=False,
                hidden_fields=[
                    ew.HiddenField(
                        name="categoryid",
                        attrs={'value': skill['skill'].trove_cat_id},
                        show_errors=False)
                ],
                fields=[
                    ffw.DisplayOnlyField(text=skill['skill'].fullpath),
                    ffw.DisplayOnlyField(text=skill['level']),
                    ffw.DisplayOnlyField(text=comment),
                    ew.SubmitButton(
                        show_label=False,
                        attrs={'value': 'Remove'},
                        show_errors=False)])]
        return super(ForgeForm, self).display(**kw)

    @ew_core.core.validator
    def to_python(self, kw, state):
        d = super(RemoveSkillForm, self).to_python(kw, state)
        d["categoryid"] = kw.get('categoryid', None)
        return d


class UploadKeyForm(ForgeForm):

    class fields(ew_core.NameList):
        key = ew.TextArea(label='SSH Public Key')


class RegistrationForm(ForgeForm):

    @property
    def fields(self):
        username = ew.TextField(
            name='username',
            label='Desired Username',
            validator=fev.Regex(
                h.re_project_name))
        username.validator._messages['invalid'] = (
            'Usernames must include only letters, numbers, and dashes.'
            ' They must also start with a letter and be at least 3 characters'
            ' long.')
        return [
            ew.TextField(
                name='display_name',
                label='Displayed Name',
                validator=fev.UnicodeString(not_empty=True)),
            username,
            ew.PasswordField(
                name='pw',
                label='New Password',
                validator=fev.UnicodeString(
                    not_empty=True,
                    min=asint(tg.config.get('auth.min_password_len', 6)),
                    max=asint(tg.config.get('auth.max_password_len', 30)))),
             ew.PasswordField(
                name='pw2',
                label='New Password (again)',
                validator=fev.UnicodeString(not_empty=True)),
        ]

    @ew_core.core.validator
    def to_python(self, value, state):
        d = super(RegistrationForm, self).to_python(value, state)
        value['username'] = username = value['username'].lower()
        if M.User.by_username(username):
            raise formencode.Invalid(
                'That username is already taken. Please choose another.',
                value, state)
        if d['pw'] != d['pw2']:
            raise formencode.Invalid('Passwords must match', value, state)
        return d


class AdminForm(ForgeForm):
    template = 'jinja:allura:templates/widgets/admin_form.html'


class NeighborhoodOverviewForm(ForgeForm):
    template = 'jinja:allura:templates/widgets/neighborhood_overview_form.html'

    class fields(ew_core.NameList):
        name = ew.TextField()
        redirect = ew.TextField()
        homepage = ffw.AutoResizeTextarea()
        allow_browse = ew.Checkbox(label='')
        show_title = ew.Checkbox(label='')
        css = ffw.AutoResizeTextarea()
        project_template = ffw.AutoResizeTextarea(
            validator=V.JsonValidator(if_empty=''))
        icon = ew.FileField()
        tracking_id = ew.TextField()
        project_list_url = ew.TextField(validator=fev.URL())
        anchored_tools = ffw.AutoResizeTextarea()
        prohibited_tools = ffw.AutoResizeTextarea()

    def from_python(self, value, state):
        if value.features['css'] == "picker":
            self.list_color_inputs = True
            self.color_inputs = value.get_css_for_picker()
        else:
            self.list_color_inputs = False
            self.color_inputs = []
        return super(NeighborhoodOverviewForm, self).from_python(value, state)

    def display_field(self, field, ignore_errors=False):
        if field.name == "css" and self.list_color_inputs:
            display = '<table class="table_class">'
            ctx = self.context_for(field)
            for inp in self.color_inputs:
                additional_inputs = inp.get('additional', '')
                empty_val = False
                if inp['value'] is None or inp['value'] == '':
                    empty_val = True
                display += '<tr><td class="left"><label>%(label)s</label></td>'\
                           '<td><input type="checkbox" name="%(ctx_name)s-%(inp_name)s-def" %(def_checked)s>default</td>'\
                           '<td class="right"><div class="%(ctx_name)s-%(inp_name)s-inp"><table class="input_inner">'\
                           '<tr><td><input type="text" class="%(inp_type)s" name="%(ctx_name)s-%(inp_name)s" '\
                           'value="%(inp_value)s"></td><td>%(inp_additional)s</td></tr></table></div></td></tr>\n' % {'ctx_id': ctx['id'],
                                                                                                                      'ctx_name': ctx['name'],
                                                                                                                      'inp_name': inp['name'],
                                                                                                                      'inp_value': inp['value'],
                                                                                                                      'label': inp['label'],
                                                                                                                      'inp_type': inp['type'],
                                                                                                                      'def_checked': 'checked="checked"' if empty_val else '',
                                                                                                                      'inp_additional': additional_inputs}
            display += '</table>'

            if ctx['errors'] and field.show_errors and not ignore_errors:
                display = "%s<div class='error'>%s</div>" % (display,
                                                             ctx['errors'])

            return h.html.literal(display)
        else:
            return super(NeighborhoodOverviewForm, self).display_field(field, ignore_errors)

    @ew_core.core.validator
    def to_python(self, value, state):
        d = super(NeighborhoodOverviewForm, self).to_python(value, state)
        neighborhood = M.Neighborhood.query.get(name=d.get('name', None))
        if neighborhood and neighborhood.features['css'] == "picker":
            css_form_dict = {}
            for key in value.keys():
                def_key = "%s-def" % (key)
                if key[:4] == "css-" and def_key not in value:
                    css_form_dict[key[4:]] = value[key]
            d['css'] = M.Neighborhood.compile_css_for_picker(css_form_dict)
        return d

    def resources(self):
        for r in super(NeighborhoodOverviewForm, self).resources():
            yield r
        yield ew.CSSLink('css/colorPicker.css')
        yield ew.CSSLink('css/jqfontselector.css')
        yield ew.CSSScript('''
table.table_class, table.input_inner{
  margin: 0;
  padding: 0;
  width: 99%;
}

table.table_class .left{ text-align: left; }
table.table_class .right{ text-align: right; width: 50%;}
table.table_class tbody tr td { border: none; }
table.table_class select.add_opt {width: 5em; margin:0; padding: 0;}
        ''')
        yield ew.JSLink('js/jquery.colorPicker.js')
        yield ew.JSLink('js/jqfontselector.js')
        yield ew.JSScript('''
            $(function(){
              $('.table_class').find('input[type="checkbox"]').each(function(index, element) {
                var cb_name = $(this).attr('name');
                var inp_name = cb_name.substr(0, cb_name.length-4);
                var inp_el = $('div[class="'+inp_name+'-inp"]');

                if ($(this).attr('checked')) {
                  inp_el.hide();
                }

                $(element).click(function(e) {
                  if ($(this).attr('checked')) {
                    inp_el.hide();
                  } else {
                    inp_el.show();
                  }
                });
              });

              $('.table_class').find('input.color').each(function(index, element) {
                $(element).colorPicker();
              });
              $('.table_class').find('input.font').each(function(index, element) {
                $(element).fontSelector();
              });
            });
        ''')


class NeighborhoodAddProjectForm(ForgeForm):
    template = 'jinja:allura:templates/widgets/neighborhood_add_project.html'
    antispam = True
    defaults = dict(
        ForgeForm.defaults,
        method='post',
        submit_text='Start',
        neighborhood=None)

    @property
    def fields(self):
        provider = plugin.ProjectRegistrationProvider.get()
        tools_options = []
        for ep, tool in g.entry_points["tool"].iteritems():
            if tool.status == 'production' and tool._installable(tool_name=ep,
                                                                 nbhd=c.project.neighborhood,
                                                                 project_tools=[]):
                tools_options.append(ew.Option(label=tool.tool_label, html_value=ep))

        return ew_core.NameList([
            ew.HiddenField(name='project_description', label='Public Description'),
            ew.HiddenField(name='neighborhood', label='Neighborhood'),
            ew.Checkbox(name='private_project', label="", attrs={'class': 'unlabeled'}),
            ew.InputField(name='project_name', label='Project Name',
                          field_type='text',
                          validator=formencode.All(
                              fev.UnicodeString(not_empty=True, max=40),
                              V.MaxBytesValidator(max=40)),
                          ),
            ew.InputField(name='project_unixname',
                          label='Short Name', field_type='text',
                          validator=provider.shortname_validator),
            ew.CheckboxSet(name='tools', options=tools_options),
        ])

    def resources(self):
        for r in super(NeighborhoodAddProjectForm, self).resources():
            yield r
        yield ew.CSSLink('css/add_project.css')
        neighborhood = g.antispam.enc('neighborhood')
        project_name = g.antispam.enc('project_name')
        project_unixname = g.antispam.enc('project_unixname')

        yield ew.JSScript('''
            $(function(){
                var $scms = $('input[type=checkbox].scm');
                var $nbhd_input = $('input[name="%(neighborhood)s"]');
                var $name_input = $('input[name="%(project_name)s"]');
                var $unixname_input = $('input[name="%(project_unixname)s"]');
                var $url_fragment = $('#url_fragment');
                var $form = $name_input.closest('form');
                var delay = (function(){
                  var timers = {};
                  return function(callback, ms){
                    clearTimeout (timers[callback]);
                    timers[callback] = setTimeout(callback, ms);
                  };
                })();
                $name_input.focus();
                var update_icon = function($input) {
                    var $success_icon = $input.parent().next().find('.success_icon');
                    var $error_icon = $input.parent().next().find('.error_icon');
                    var is_error = $input.nextAll('.error').is(':visible');
                    $success_icon.toggle(!is_error);
                    $error_icon.toggle(is_error);
                };
                if ($name_input.val() !== '') {
                    update_icon($name_input);
                }
                if ($unixname_input.val() !== '') {
                    update_icon($unixname_input);
                }
                var handle_error = function($input, message) {
                    var $error_field = $input.nextAll('.error');
                    if ($error_field.length === 0) {
                        $error_field = $('<div class="error" style="display: none"></div>').insertAfter($input);
                    }
                    $error_field.text(message).toggle(!!message);
                    update_icon($input);
                };
                $form.submit(function(e) {
                    var has_errors = $name_input.add($unixname_input).nextAll('.error').is(':visible');
                    if (has_errors || $name_input.val() === '' || $unixname_input.val() === '') {
                        e.preventDefault();
                        alert('You must resolve the issues with the project name.');
                        return false;
                    }
                });
                $scms.change(function(){
                    if ( $(this).attr('checked') ) {
                        var on = this;
                        $scms.each(function(){
                            if ( this !== on ) {
                                $(this).removeAttr('checked');
                            }
                        });
                    }
                });
                var check_names = function() {
                    var data = {
                        'neighborhood': $nbhd_input.val(),
                        'project_name': $name_input.val(),
                        'project_unixname': $unixname_input.val()
                    };
                    $.getJSON('check_names', data, function(result){
                        handle_error($name_input, result.project_name);
                        handle_error($unixname_input, result.project_unixname);
                    });
                };
                var manual = false;
                $name_input.keyup(function(){
                    delay(function() {
                        if (!manual) {
                            var data = {
                                'project_name':$name_input.val()
                            };
                            $.getJSON('suggest_name', data, function(result){
                                $unixname_input.val(result.suggested_name);
                                $url_fragment.text(result.suggested_name);
                                check_names();
                            });
                        } else {
                            check_names();
                        }
                    }, 500);
                });
                $unixname_input.change(function() {
                    manual = true;
                });
                $unixname_input.keyup(function(){
                    $url_fragment.text($unixname_input.val());
                    delay(check_names, 500);
                });
            });
        ''' % dict(neighborhood=neighborhood, project_name=project_name, project_unixname=project_unixname))


class MoveTicketForm(ForgeForm):
    defaults = dict(
        ForgeForm.defaults,
        action='',
        method='post',
        submit_text='Move')

    class fields(ew_core.NameList):
        tracker = ew.SingleSelectField(
            label='Tracker mount point',
            options=[])

    def __init__(self, *args, **kwargs):
        trackers = kwargs.pop('trackers', [])
        super(MoveTicketForm, self).__init__(*args, **kwargs)
        self.fields.tracker.options = (
            [ew.Option(py_value=v, label=l, selected=s)
             for v, l, s in sorted(trackers, key=lambda x: x[1])])


class CsrfForm(ew.SimpleForm):

    @property
    def hidden_fields(self):
        return [ew.HiddenField(name='_session_id')]

    def context_for(self, field):
        ctx = super(CsrfForm, self).context_for(field)
        if field.name == '_session_id':
            ctx['value'] = tg.request.cookies.get('_session_id')
        return ctx


class AwardGrantForm(ForgeForm):

    def __init__(self, *args, **kw):
        self._awards = kw.pop('awards', [])
        self._project_select_url = kw.pop('project_select_url', '')
        super(AwardGrantForm, self).__init__(*args, **kw)


    def award_options(self):
        return [ew.Option(py_value=a.short, label=a.short) for a in self._awards]

    @property
    def fields(self):
        return [
            ew.SingleSelectField(
                name='grant',
                label='Award',
                options=self.award_options()),
            ffw.NeighborhoodProjectSelect(
                self._project_select_url,
                name='recipient'),
            ew.TextField(
                name='url',
                label='Award URL',
                validator=fev.URL()),
            ew.TextArea(
                name='comment',
                label='Comment',
                validator=fev.UnicodeString(not_empty=False),
                attrs={'rows': 5, 'cols': 30}),
        ]
