try:
    from html import escape
except ImportError:
    from cgi import escape

#from wtforms import widgets
from wtforms.widgets import HTMLString, html_params
from wtforms.fields.core import Field
from wtforms.compat import text_type, izip

class MySelect(object):
    """
    Renders a select field.

    If `multiple` is True, then the `size` property should be specified on
    rendering to make the field useful.

    The field must provide an `iter_choices()` method which the widget will
    call on rendering; this method must yield tuples of
    `(value, label, selected)`.
    """
    def __init__(self, multiple=False):
        self.multiple = multiple

    def __call__(self, field, **kwargs):
        kwargs.setdefault('id', field.id)
        if self.multiple:
            kwargs['multiple'] = True
        html = ['<select %s>' % html_params(name=field.name, **kwargs)]
        last_group = None
        for group, val, label, selected in field.iter_choices():
            if group is None:
                html.append(self.render_option(val, label, selected))
            elif last_group != group:
                html.append(self.render_optgroup(last_group, group))
                html.append(self.render_option(val, label, selected))
                last_group=group
            else:
                html.append(self.render_option(val, label, selected))
        if last_group:
            html.append(self.render_optgroup(last_group, None))
        html.append('</select>')
        return HTMLString(''.join(html))

    @classmethod
    def render_option(cls, value, label, selected, **kwargs):
        if value is True:
            # Handle the special case of a 'True' value.
            value = text_type(value)

        options = dict(kwargs, value=value)
        if selected:
            options['selected'] = True
        return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label), quote=False)))

    @classmethod
    def render_optgroup(cls, previous_label, label, **kwargs):
        options = dict(kwargs)
        if previous_label is None:
            return HTMLString('<optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))
        elif label is None:
            return HTMLString('</optgroup>')
        else:
            return HTMLString('</optgroup><optgroup %s label="%s">' % (html_params(**options), escape(text_type(label), quote=False)))


class MyOption(object):
    """
    Renders the individual option from a select field.

    This is just a convenience for various custom rendering situations, and an
    option by itself does not constitute an entire field.
    """
    def __call__(self, field, **kwargs):
        return MySelect.render_option(field._value(), field.label.text, field.checked, **kwargs)


class MySelectFieldBase(Field):
    #option_widget = widgets.Option()
    option_widget = MyOption()

    """
    Base class for fields which can be iterated to produce options.

    This isn't a field, but an abstract base class for fields which want to
    provide this functionality.
    """
    def __init__(self, label=None, validators=None, option_widget=None, **kwargs):
        super(MySelectFieldBase, self).__init__(label, validators, **kwargs)

        if option_widget is not None:
            self.option_widget = option_widget

    def iter_choices(self):
        """
        Provides data for choice widget rendering. Must return a sequence or
        iterable of (value, label, selected) tuples.
        """
        raise NotImplementedError()

    def __iter__(self):
        opts = dict(widget=self.option_widget, _name=self.name, _form=None, _meta=self.meta)
        for i, (value, label, checked) in enumerate(self.iter_choices()):
            opt = self._Option(label=label, id='%s-%d' % (self.id, i), **opts)
            opt.process(None, value)
            opt.checked = checked
            yield opt

    class _Option(Field):
        checked = False

        def _value(self):
            return text_type(self.data)


class MySelectField(MySelectFieldBase):
    #widget = widgets.Select()
    widget = MySelect()

    def __init__(self, label=None, validators=None, coerce=text_type, choices=None, **kwargs):
        super(MySelectField, self).__init__(label, validators, **kwargs)
        self.coerce = coerce
        self.choices = choices

    def iter_choices(self):
        for choiceA, choiceB in self.choices:
            if isinstance(choiceB, (tuple, list)):
                # We should consider choiceA as an optgroup label
                group_label = choiceA
                for value, label in choiceB:
                    yield (group_label, value, label, self.coerce(value) == self.data)
            else:
                value, label = choiceA, choiceB
                # Not an optgroup, let's fallback to classic usage
                yield (None, value, label, self.coerce(value) == self.data)

    def process_data(self, value):    
        try:
            self.data = self.coerce(value)           
        except (ValueError, TypeError):
            self.data = None

    def process_formdata(self, valuelist):
        if valuelist:
            try:
                self.data = self.coerce(valuelist[0])
            except ValueError:
                raise ValueError(self.gettext('Invalid Choice: could not coerce'))

    def pre_validate(self, form):
        for choiceA, choiceB in self.choices:
            if isinstance(choiceB, (tuple, list)):        
                for value, label in choiceB:
                    if self.data == value:
                        break
                if self.data == value:
                    break
            else:
                value, label = choiceA, choiceB
                if self.data == value:
                    break
        else:
            raise ValueError(self.gettext('Not a valid choice'))
