class AjaxAutoSelect(forms.Select):
    """
    May not work for all possible widget types for the related field
    (simple html form widgets should be okay, we listen to jQuery 'change' event)
    """
    related_field = ''
    def render(self, name, value, attrs=None, choices=()):
        self._element_id = attrs['id']
        
        # normal widget output from the ancestor
        # create a field with a dummy name, the real value
        # will be retrieved from a hidden field
        parent_output = super(AjaxAutoSelect, self).render("dummy-%s" % name, value, attrs, choices)
        
        # output
        if value is None:
            value = ''
        mapping = {
            "related_field": self.related_field,
            "parent_output": parent_output,
            "name": name,
            "element_id": self._element_id, 
            "value": value,
            'app_label': self.model._meta.app_label,
            'object_name': self.model._meta.object_name,
            'select_related': self.select_related,
        }
        
        # TO DO:
        # we shouldn't SelectBox.empty() if we're editing an existing record that has a value in the related field
        output = u"""
            <input type="hidden" name="%(name)s" id="hidden-%(element_id)s" value="%(value)s" />
            
            %(parent_output)s
            
            <script type="text/javascript" charset="utf-8">
        		$(document).ready(function(){
                    SelectBox.init('%(element_id)s');
                    if (!$('#id_%(related_field)s').val()) {
                        SelectBox.empty('%(element_id)s');
                    }
                    
                    ajax_filtered_fields.bindForeignKeyOptions("%(element_id)s");
                    
                    $('#id_%(related_field)s').change(function(evt){
                        ajax_filtered_fields.getForeignKeyJSON('%(element_id)s', '%(app_label)s', '%(object_name)s', '%(related_field)s__pk='+$(evt.target).val(), '%(select_related)s');
                    });
        		});
        	</script>
            """ % mapping
            
        return mark_safe(output)


class AjaxFilteredForeignKeyField(forms.ModelChoiceField):
    def __init__(self, model, field_name, widget=AjaxAutoSelect, *args, **kwargs):
        queryset = model.objects.none()
        super(AjaxFilteredForeignKeyField, self).__init__(queryset, widget=widget, *args, **kwargs)
        
        self.isFilteredForeignKeyField = True
        self.widget.model = self.model = model
        self.widget.related_field = self.related_field = field_name
        self.widget.select_related = None


class AjaxFilteredFKFieldsForm(forms.ModelForm):
    def __init__(self, initial=None, *args, **kwargs):
        super(AjaxFilteredFKFieldsForm, self).__init__(initial=initial, *args, **kwargs)
        for field_name in self.fields:
            field = self.fields[field_name]
            if getattr(field, 'isFilteredForeignKeyField', False):
                if field.related_field in self.initial:
                    # sometimes it's a list with one member, sometimes it's just a number (awesome!)
                    try:
                        fk_val = self.initial.get(field.related_field, self.fields[field.related_field].initial)[0]
                    except TypeError:
                        fk_val = self.initial.get(field.related_field, self.fields[field.related_field].initial)
                    fargs = {'%s__pk'%field.related_field: fk_val}
                    field.queryset = field.model.objects.filter(**fargs)