
$.fn.remoteValidate = function(conf) {
    var inputTypes = [
        'input[type=text]',        
        'input[type=checkbox]',
        'input[type=password]',
        'input[type=radio]',
        'input[type=hidden]',
        'select',
        'textarea'
    ].join(',')
    
    function showError(field, message) {
        var div = $(field.parentNode).children('.error')
        if(!div[0]) {
            div = $('<div class="error"></div>').appendTo(field.parentNode)
        }
        div.html(message || '').show()
    }
    function hideError(field) {
        $(field.parentNode).children('.error').html('').hide()
    }    
    
    this.each(function() {
        var jform = $(this)
        var url = jform.attr('action')
        
        // Prevent accidentally calling remoteValidate twice on 
        // the same form
        if(jform.data('hasRemoteValidate')) 
            return // <-- continue
            
        jform.data('hasRemoteValidate', true)
        
        // Add onchange listener to all contained fields
        jform.find(inputTypes).change(function() {
            var field = this
            var data = {} 
            data[this.name] = this.value
            $.ajax({
                url: url,
                type: jform.find('input[name=_method]').attr('value') || 'post',
                dataType: 'json',
                data: data,
                beforeSend: function(xmlhttp) {
                    xmlhttp.setRequestHeader('X-Validate', '1')
                },                
                error: function(xmlhttp, b, c) {
                    eval('var errors='+xmlhttp.responseText)
                    showError(field, errors[field.name])
                },
                success: function() {                    
                    console.log('HIDE2: ', this.name)
                    hideError(field)
                }
            })
        })
        
        // Add an onsubmit listener posting the form using ajax
        var onsubmit = function() {
            var data = []
            var success = true
            var groups = {}
            var uncheked = {}
            
            jform.find(inputTypes).each(function() {    
                var type = this.type ? this.type.toLowerCase() : ''
                var is_text = $.inArray(type, ['text', 'password']) !== -1
                var is_textarea = this.tagName.toLowerCase() == 'textarea'
                var is_select = this.tagName.toLowerCase() == 'select'
                var is_checkable = type == 'checkbox'
                var is_radio = type == 'radio'
                
                if((is_text || is_textarea || is_select)) {
                    data.push([this.name, this.value.replace(/&/g, '&amp;')]) // escape(this.value)
                }
                else if(is_checkable) {
                    groups[this.name] = true
                    if(this.checked)
                        data.push([this.name, this.value.replace(/&/g, '&amp;')]) // escape(this.value)
                }
                else if(is_radio) {
                    groups[this.name] = true
                    if(this.checked) {
                        data.push([this.name, this.value.replace(/&/g, '&amp;')]) // escape(this.value)                        
                    }
                }                    
            })
            
            // Make sure even unchecked checkboxes etc are added
            // to the post body
            for(var name in groups) {
                var exists = false
                $.each(data, function(i, tup){
                    if(tup[0] == name) {
                        exists = true
                        return false; // break
                    }
                });
                if(!exists) {
                    data.push([name, ''])
                }
            }
            
            
            data = $.map(data, function(tup) { 
                return tup[0]+'='+tup[1].replace(/&/g, '&amp;') // escape(tup[1])
            }).join('&')
            
            $.ajax({
                url: url,
                type: jform.find('input[name=_method]').attr('value') || 'post',
                dataType: 'json',
                // dataType: "application/x-www-form-urlencoded",
                data: data,
                beforeSend: function(xmlhttp) {
                    xmlhttp.setRequestHeader('X-Validate', '1')
                    // xmlhttp.setRequestHeader('Content-type', 'x-www-form-urlencoded')
                },
                error: function(xmlhttp, textStatus, errorThrown) {
                    eval('var errors=' +xmlhttp.responseText)
                    
                    var visited = {}
                    var scrolltop = 100000;
                    $(jform.find(inputTypes).get()).each(function() {
                        if(errors[this.name] && !visited[this.name]) {
                            showError(this, errors[this.name])
                            scrolltop = Math.min(scrolltop, $(this).position().top);
                        }
                        else if(!errors[this.name]) {
                            hideError(this)
                        }
                        visited[this.name] = true
                    })

                    if(scrolltop != 100000) {
                        $('html,body').animate({scrollTop:Math.max(0,scrolltop-150)}, 500);
                        // $(window.document).scrollTop(scrolltop)                        
                    }
                    return false
                },
                success: function(a,b,c,d) {
                    if(!jform.data('stop')) {
                        // Whole form posted for validation successfully
                        // Now post the form "for real" (w/o X-Validate header)
                        jform.unbind('submit', onsubmit)
                        jform.data('valid', true)
                        
                        // Check if successful post should redirect
                        // Todo: implement this with events instead of funny made-up "forwardsuccess" thingie.
                        var forward = jform.attr('forwardsuccess');
                        if(forward) {
                            jform.attr('action', forward);
                        }
                        jform.submit()
                        jform.data('valid', false)                    
                        // prevent submitting twice 
                        // jform.submit(function() {return false})
                        jform.submit(onsubmit)                    
                    }
                }
                // complete: function(a,b,c,d) {
                // }
            })  
            return false
        }
        jform.submit(onsubmit)
    })
    return this
}
