# (c) Svarga project under terms of the new BSD license

from functools import partial
from procrustes import validators


class Forms(object):
    def __init__(self):
        self.fields = {}

    def __getattr__(self, field):
        if field in self.fields:
            return partial(create_field, field)
        raise AttributeError(validator)

    def register(self, *args):
        largs = len(args)
        def wrapper(field):
            field_name = args[0] if largs else field.__name__
            self.register(field_name, field)
            return field

        if largs==2:
            self.fields[args[0]] = args[1]
        else:
            return wrapper

forms = Forms()


def create_field(field, *args, **kwargs):
    cls = forms.fields[field]
    new_cls = type('Pc' + field, (cls, ), {})
    new_cls.required = kwargs.pop('required', True)
    new_cls.base_field_configure(*args, **kwargs)
    new_cls.configure(*args, **kwargs)
    return new_cls


class FieldMixin(object):
    @classmethod
    def base_field_configure(cls, *args, **kwargs):
        cls.widget = kwargs.pop('widget', BaseWidget)
        cls.field_configure(*args, **kwargs)

    @classmethod
    def field_configure(cls, *args, **kwargs):
        pass

    def widgets(self, id):
        yield self.widget(data=self.data, id=id)


@forms.register()
class Tuple(FieldMixin, validators.Tuple):
    def widgets(self, id=''):
        prefix = id + '__' if id else ''
        data = self.get_included()
        for num, field in enumerate(data):
            for widget in field.widgets(prefix + str(num)):
                yield widget


@forms.register()
class String(FieldMixin, validators.String):
    pass


class BaseWidget(object):
    def __init__(self, **kwargs):
        self.data = kwargs.pop('data', None)
        self.id = kwargs.get('id')
        self.attrs = kwargs

    def render(self):
        data = self.data if self.data else ''
        attrs = ' '.join('%s="%s"' % (name, attr) for name, attr
                                                in self.attrs.iteritems())
        if attrs:
            attrs += ' '
        return '<input %svalue="%s">' % (attrs, data)


if __name__ == '__main__':
    from attest import Tests, Assert
    p = Tests()

    @p.test
    def simple():
        str = forms.String()('kukuku')
        Assert(str.data) == 'kukuku'

        FT = forms.Tuple(forms.String(), forms.String())
        ft = FT(None)
        widgets = [widget.render() for widget in ft.widgets()]
        Assert(widgets) == ['<input id="0" value="">', '<input id="1" value="">']

        ft = FT(('kuku', 'kuku'))
        widgets = [widget.render() for widget in ft.widgets('form')]
        Assert(widgets) == ['<input id="form__0" value="kuku">', '<input id="form__1" value="kuku">']
        #Assert(str.render('strid')) == '<input id="strid" value="kukuku">'

    p.run()

@@ -1320,66 +1320,34 @@
 )%0A%0A%0A
-@forms.register()%0Aclass Tuple(FieldMixin, validators.Tuple
+class IterableMixin(object
 ):%0A 
@@ -1585,16 +1585,485 @@
 idget%0A%0A%0A
+@forms.register()%0Aclass Tuple(IterableMixin, FieldMixin, validators.Tuple):%0A    pass%0A%0A%0A@forms.register()%0Aclass List(IterableMixin, FieldMixin, validators.List):%0A    pass%0A%0A%0A@forms.register()%0Aclass Dict(FieldMixin, validators.Dict):%0A    def widgets(self, id=''):%0A        prefix = id + '__' if id else ''%0A        data = self.get_included()%0A        for name, field in data.iteritems():%0A            for widget in field.widgets(prefix + name):%0A                yield widget%0A%0A%0A
 @forms.r
@@ -2845,24 +2845,64 @@
 s.String())%0A
+        FL = forms.List(forms.String())%0A
         ft =
@@ -3220,24 +3220,52 @@
 ue=%22kuku%22%3E',
+%0A                           
  '%3Cinput id=
@@ -3365,16 +3365,902 @@
 ukuku%22%3E'
+%0A        fl = FL(%5B'kuku', 'dsfasfd', 'xcvxczvx'%5D)%0A        widgets = %5Bwidget.render() for widget in fl.widgets('form')%5D%0A        Assert(widgets) == %5B'%3Cinput id=%22form__0%22 value=%22kuku%22%3E',%0A                            '%3Cinput id=%22form__1%22 value=%22dsfasfd%22%3E',%0A                            '%3Cinput id=%22form__2%22 value=%22xcvxczvx%22%3E'%5D%0A%0A    @p.test%0A    def dict_field():%0A        FD = forms.Dict(%7B'a': forms.String(), 'b': forms.String()%7D)%0A        fd = FD(None)%0A        widgets = %5Bwidget.render() for widget in fd.widgets('form')%5D%0A        Assert(widgets) == %5B'%3Cinput id=%22form__a%22 value=%22%22%3E',%0A                            '%3Cinput id=%22form__b%22 value=%22%22%3E'%5D%0A%0A        fd = FD(%7B'a': 'kuku', 'b': 'may-may'%7D)%0A        widgets = %5Bwidget.render() for widget in fd.widgets('form')%5D%0A        Assert(widgets) == %5B'%3Cinput id=%22form__a%22 value=%22kuku%22%3E',%0A                            '%3Cinput id=%22form__b%22 value=%22may-may%22%3E'%5D
 %0A%0A    p.

Add more fields