/*
 * jQuery CodeIgniter Form Class JavaScript v0.1
 * http://coffeebeandesign.com/
 *
 * Copyright (c) 2009 Coffee Bean Design
 * Licensed under the GPL licenses.
 *
 * Date: 2009-08-02 12:00:00 GMT (Sat, 01 Aug 2009)
 * Revision: 1
 */

(function ($) {
    var options = {};
    var error_array = [];
    $.fn.ciFV = function (params) {
        options = $.extend({},
        $.fn.ciFV.defaults, params);
        return this.each(function () {
           if (options.submit_button != '' && $(options.submit_button).length > 0) {
                $(options.submit_button).bind('click', {
                    form: this,
                    options: options
                },
                $(this).ciFV.validate)
            } else {
                $(this).bind('submit', {
                    form: this,
                    options: options
                },
                $(this).ciFV.validate)
            }
        })
    };
    $.fn.ciFV.defaults = {
		error_display: 'one',
        error_format: 'div',
        error_div: '',
        error_position: 'top',
        error_tag: 'p',
		error_class: 'warning',
        error_container_class: 'warning',
        error_bullet: '',
        error_intro: '',
		submit_button: '',
		error_alert: false,

        on_error: null,
        on_complete: null,
        on_valid: null,
        rules: []
    };
    $.fn.ciFV.validate = function (event) {

        options = event.data.options;
        var form = event.data.form;
        var rules = options.rules;
		var error_open = '<' + options.error_tag;
		if (options.error_class != '') {error_open += ' class="' + options.error_class + '"'}
		error_open += '>';
		var error_close = '</' + options.error_tag + '>'; 
		
		error_array = [];
        for (var i = 0; i < rules.length; i++) {
            var row = rules[i].replace(/\\,/ig, "%%C%%");
            row = row.split(",");
            var rule = row[0];
            var field_name = row[1];
            var error_message = row[2];
            var param = row[3];
            if (rule != "function" && options.error_container_class) {
                $(form[field_name]).parent().removeClass(options.error_container_class)
            }
			
			if (options.error_class != '') {$(form[field_name]).parent().find('.' + options.error_class).remove();}
			
            switch (rule) {
            case "required":
                if (form[field_name].type == undefined) {
                    var oneIsChecked = false;
                    for (var j = 0; j < form[field_name].length; j++) {
                        if (form[field_name][j].checked) {
                            oneIsChecked = true
                        }
                    }
                    if (!oneIsChecked) {
                        process_error(form[field_name], error_message)
                    }
                } else if (form[field_name].type == "select-multiple") {
                    var oneIsSelected = false;
                    for (var k = 0; k < form[field_name].length; k++) {
                        if (form[field_name][k].selected) {
                            oneIsSelected = true
                        }
                    }
                    if (!oneIsSelected || form[field_name].length == 0) {
                        process_error(form[field_name], error_message)
                    }
                } else if (form[field_name].type == "checkbox") {
                    if (!form[field_name].checked) {
                        process_error(form[field_name], error_message)
                    }
                } else if (!form[field_name].value) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "matches":
                if (form[field_name].value != form[param].value) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "min_length":
                if (form[field_name].value.length < parseInt(param)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "max_length":
                if (form[field_name].value.length > parseInt(param)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "exact_length":
                if (form[field_name].value.length == parseInt(param)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "alpha":
                if ( ! form[field_name].value.match(/[a-z]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "alpha_numeric":
                if ( ! form[field_name].value.match(/[a-z0-9]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "alpha_dash":
                if ( ! form[field_name].value.match(/[-a-z0-9_-]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "numeric":
                if ( ! form[field_name].value.match(/[\-+]?[0-9]*\.?[0-9]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "integer":
                if ( ! form[field_name].value.match(/[\-+]?[0-9]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "is_natural":
                if ( ! form[field_name].value.match(/[0-9]/i)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "is_natural_no_zero":
                if ( form[field_name].value == "0" || ! form[field_name].value.match(/[0-9]/i) ) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "valid_email":
                if (form[field_name].value && !is_valid_email(form[field_name].value)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "valid_emails":
                emails = form[field_name].value.split(",");
                for (var e = 0; e < emails.length; e++) {
                    if (!is_valid_email(e[0])) {
                        process_error(form[field_name], error_message)
                    }
                }
                break;
            case "valid_ip":
                var ip_value = form[field_name].value;
                var ip_pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
                var ip_array = ip_value.match(ip_pattern);
                var ip_error = false;
                if (ip_value == "0.0.0.0" || ip_value == "255.255.255.255" || ip_array == null) {
                    ip_error = true
                } else {
                    for (i = 0; i < 4; i++) {
                        seg = ip_array[i];
                        if (seg > 255) {
                            ip_error = true;
                            i = 4
                        }
                        if ((i == 0) && (seg > 255)) {
                            ip_error = true;
                            i = 4
                        }
                    }
                }
                if (ip_error) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "valid_base64":
                if ( form[field_name].value != 0 && form[field_name].value.match(/^[a-zA-Z0-9\/\+=]/)) {
                    process_error(form[field_name], error_message)
                }
                break;
            case "callback":			
				if (eval("typeof " + param + " == 'function'")) {
					callback_function = eval(param);
					callback_result = callback_function(form[field_name].value);
					if ( ! callback_result){
						process_error(form[field_name], error_message)	
					}
				}
				break
            }
        }
        if (error_array.length == 0) {
            if (typeof options.on_valid == 'function') {
                return options.on_valid(form, error_array)
            } else {
                return true
            }
        } else {
            if (typeof options.on_error == 'function') {
                return options.on_error(form, error_array)
            } else if (options.error_alert == true) {
                var alert_string = options.error_intro + "\n";
                for (var i = 0; i < error_array.length; i++) {
                    alert_string += options.error_bullet + error_array[i][1] + "\n";
                    style_field(error_array[i][0], i == 0);
                    if (options.error_display == 'one' && i == 0) {
                        break
                    }
                }
                alert(alert_string)
            } else if (options.error_format != 'inline') {
                var html_string = '';
                if (options.error_intro != '') {
                    html_string += '<p class="error_intro"' + options.error_intro + '</p>'
                }
                for (var i = 0; i < error_array.length; i++) {
                    html_string += error_open + options.error_bullet + error_array[i][1] + error_close;
                    style_field(error_array[i][0]);
                    if (options.error_display == 'one' && i == 0) {
                        $(error_array[i][0]).focus();
                        break
                    }
                }
                if (options.error_div != '') {
					
					var ed = $("#" + options.error_div);
					if (ed.length > 0) {
                     	$(ed).html(html_string);
                     } else {
						string = '<div id="' + options.error_div + '">' + html_string + '</div>';
                        if (options.error_position == 'bottom') {
                            $('body').append(string)
                        } else {
                            $('body').prepend(string)
                        }
                    }
                } else {
					
					default_error_div = $('input[name=form_id]').val() + '_errors';
					
                    $('#' + default_error_div).remove();
                    var string = '<div class="form_errors" id="' + default_error_div + '">' + html_string + '</div>';
                    if (options.error_position == 'bottom') {
                        $(form).append(string)
                    } else {
                        $(form).prepend(string)
                    }
                }
            } else {
                for (var i = 0; i < error_array.length; i++) {
                    var html_string = '';
                    html_string += error_open + options.error_bullet + error_array[i][1] + error_close;
                    style_field(error_array[i][0]);
                    if (options.error_position == 'bottom') {
						$(error_array[i][0]).parent().append(html_string);
					} else {
						$(error_array[i][0]).parent().prepend(html_string);
					}
                    if (options.error_display == 'one' && i == 0) {
                        $(error_array[i][0]).focus();
                        break
                    }
                }
            }
            if (typeof options.on_complete == 'function') {
                options.on_complete(form, error_array)
            }
            return false
        }
    }
    function style_field(field) {
        if (options.error_container_class != null) {
            $(field).parent().addClass(options.error_container_class)
        }
    }
    function process_error(obj, message) {
        message = message.replace(/%%C%%/ig, ",");
        error_array.push([obj, message])
    }
    function is_valid_email(str) {
        var s = $.trim(str);
        var at = "@";
        var dot = ".";
        var lat = s.indexOf(at);
        var lstr = s.length;
        var ldot = s.indexOf(dot);
        if (s.indexOf(at) == -1 || (s.indexOf(at) == -1 || s.indexOf(at) == 0 || s.indexOf(at) == lstr) || (s.indexOf(dot) == -1 || s.indexOf(dot) == 0 || s.indexOf(dot) == lstr) || (s.indexOf(at, (lat + 1)) != -1) || (s.substring(lat - 1, lat) == dot || s.substring(lat + 1, lat + 2) == dot) || (s.indexOf(dot, (lat + 2)) == -1) || (s.indexOf(" ") != -1)) {
            return false
        }
        return true
    }
})(jQuery);
