/**
 * Ajax request handling function
 */
function ServerAjaxFullRequest(method, url, data) {

    if (DEBUG) alert('DEBUG INFO: ' + url);

    /** block user interface */
    $.blockUI();

//    /** create XmlHttpRequest object to handle request */
//    var XHR;
//    try {
//        /** Opera 8.0+, Firefox, Safari */
//        XHR = new XMLHttpRequest();
//    } catch (e) {
//        /** Internet Explorer Browsers */
//        try {
//            XHR = new ActiveXObject("Msxml2.XMLHTTP");
//        } catch (e) {
//            try {
//                XHR = new ActiveXObject("Microsoft.XMLHTTP");
//            } catch (e) {
//                /** not supported */
//                alert("Your browser doesn't support this function!");
//                exit(1);
//            }
//        }
//    }
//
//    /** send request */
//    XHR.open(method, url, false);
//    XHR.send(data);

    var XHR = $.ajax({url: url, type: method, async: false, data: data})

    /** unblock user interface */
    $.unblockUI();

    /** execute proper action */
    switch (XHR.getResponseHeader('X-ServerResponseCode')) {

        case 'OK' :
            return XHR.responseText;

        case 'Error' :
            alert('Error!\n\n' + XHR.responseText);
            break;

        case 'Info' :
            alert('Info!\n\n' + XHR.responseText);
            break;

        case 'Redirect' :
            document.location = XHR.getResponseHeader('Location');
            exit(0);

        default :
            alert('Request error.\n\n' + XHR.responseText);
            break;
    }

    return false;
}

function ServerAjaxRequest(url) {
    return ServerAjaxFullRequest("GET", url, null)
}

function XServerAjaxRequestElementInit(el) {

    $(el).click(function(event) {

        event.stopImmediatePropagation();

        /** ask user to confirm request */
        var userconfirm = $(el).attr('XActionConfirm');
        if(userconfirm && ''!=userconfirm && !confirm(userconfirm)) return;

        /** perform server request */
        var url = $(el).attr('XServerAction');
        var result = '';
        if (''!=url) {
            
            /** get element attribute value */
            var attribute = $(el).attr('XServerActionAttr');
            if (attribute) {
                attribute = 'attr=' + $(el).attr(attribute);
            } else {
                attribute = '';
            }

            /** make a request */
            result = ServerAjaxRequest(SERVICE_DIRECTORY + url + attribute);
            if (result!='' && result==false) return;
        }

        /** do callback action */
        var fname = $(el).attr('XServerResponseCB');
        if (fname && ''!=fname) {
            eval('' + fname + '(result, el);');
        }
    });
}

function ServerRequest(url) {
    if (DEBUG) alert('DEBUG INFO: ' + url)
    document.location = url
}

function XServerRequestElementInit(el) {

    $(el).click(function(event) {

        event.stopImmediatePropagation()

        /** ask user to confirm request */
        var userconfirm = $(el).attr('XActionConfirm')
        if(userconfirm && ''!=userconfirm && !confirm(userconfirm)) return

        /** perform server request */
        url = $(el).attr('XServerAction')
        if (''!=url) ServerRequest(url)
    })
}

function XActionElementInit(el) {

    $(el).click(function(event) {

        event.stopImmediatePropagation()

        /** ask user to confirm request */
        var userconfirm = $(el).attr('XActionConfirm')
        if(userconfirm && ''!=userconfirm && !confirm(userconfirm)) return false

        /** proceed with action */
        return true
    })
}

/**
 * CSS errorClass: XValidateError
 **/
function XValidateEmail(el) {
    emailPattern = new RegExp("^([a-z0-9!#$%&'*+\/=?^_`{|}~-])+(\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+([a-z]{2}|test|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)$", "g")

    /** basic check, only for valid chars without checking format of the email */
    charsValidate = new RegExp("^([a-z0-9@\.!#$%&'*+\/=?^_`{|}~-])+$", "i")
    monkeySign = new RegExp("([@]){0,1}")

    $(el).keypress(function(event) {
        if(event.charCode != 0 ) {
            value = $(el).val() + String.fromCharCode(event.charCode)
            if(value != "") {
                if(value.match(charsValidate) && value.match(monkeySign)) {
                    $(el).removeClass("XValidateError")
                    return true;
                } else {
                    event.preventDefault();
                }
            } else {
                $(el).removeClass("XValidateError")
            }
        }
    })

    $(el).blur(function() {
        value = $(el).val()
        if(value != "") {
            if(value.match(emailPattern)) {
                $(el).removeClass("XValidateError")
                return true
            } else {
                $(el).addClass("XValidateError")
            }
        } else {
            $(el).removeClass("XValidateError")
        }
    })

    
}

function XValidateDate(el) {
    var format = $(el).attr("XValidateFormat")

    var minValue = ($(el).attr("XValidateMin")) ? $.datepicker.parseDate(format, $(el).attr("XValidateMin")) : null
    var maxValue = ($(el).attr("XValidateMax")) ? $.datepicker.parseDate(format, $(el).attr("XValidateMax")) : null

    var lang = $(el).attr("XValidateLang")

    var validateDateFn = function() {
        /** check if date is valid */
        try {
            date = $.datepicker.parseDate(format, $(el).val())
        
            if(date != null) {

                if(minValue != null && date < minValue) {
                    $(el).addClass("XValidateError")
                    return;
                }

                if(maxValue != null && date > maxValue) {
                    $(el).addClass("XValidateError")
                    return;
                }
                $(el).removeClass("XValidateError")
            }
        } catch (e) {
            $(el).addClass("XValidateError")
            return;
        }
    }

    $(el).datepicker({
        dateFormat: format,
        maxDate: maxValue,
        minDate: minValue,
        onSelect: validateDateFn,
        onClose: validateDateFn
    });

    $(el).datepicker($.datepicker.regional[lang]);

    $(el).blur(validateDateFn)
}

function isNumber(n) {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

function XValidateNumber(el) {

    /** check after entering data */
    $(el).blur(function(event) {
        
        var value = $(this).val()
        var minValue = ($(this).attr("XValidateMin")) ? parseFloat($(this).attr("XValidateMin")) : null
        var maxValue = ($(this).attr("XValidateMax")) ? parseFloat($(this).attr("XValidateMax")) : null

        if (''!=value) {

            if ('-'==value || '.'==value || '-.'==value) {
                $(this).addClass("XValidateError")
                return
            }

            /** check range */
            var number = parseFloat(value)

            if(minValue != null && number < minValue) {
                $(this).addClass("XValidateError")
                return
            }

            if(maxValue != null && number > maxValue) {
                $(this).addClass("XValidateError")
                return
            }

            $(this).removeClass("XValidateError")
            
        } else {
            $(this).removeClass("XValidateError")
        }
    })

    /** check during entering data */
    $(el).keypress(function(event) {

        var minValue = ($(el).attr("XValidateMin")) ? parseFloat($(el).attr("XValidateMin")) : null
        var maxValue = ($(el).attr("XValidateMax")) ? parseFloat($(el).attr("XValidateMax")) : null
        var decimals = ($(el).attr("XValidateDecimals")) ? parseFloat($(el).attr("XValidateDecimals")) : null

        /** set up pattern */
        if (maxValue != null && maxValue < 0.0) {
            patternval = "^-(0|[1-9][0-9]*)?"
        } else if (minValue == null || minValue < 0.0) {
            patternval = "^-?(0|[1-9][0-9]*)?"
        } else {
            patternval = "^(0|[1-9][0-9]*)?"
        }
        if(decimals == null || decimals > 0) {
            patternval += "([.][0-9]{0,"+decimals+"})?"
        }
        patternval += "$"
        var pattern = new RegExp(patternval)

        /** if not backspace */
        if (event.which != 8 ) {

            /** stop entering data */
            event.preventDefault();

            inputChar = String.fromCharCode(event.which).replace(',', '.')
            var value = $(el).val() + inputChar

            if (pattern.test(value)) {

                if ('-'==value || '.'==value || '-.'==value) {
                    $(el).val(value)
                    return
                }

                /** check range */
                number = parseFloat(value)
                if(minValue != null && minValue <= 0 && number < minValue) {
                    $(this).addClass("XValidateError")
                    return
                }

                if(maxValue != null && maxValue >= 0 && number > maxValue) {
                    $(this).addClass("XValidateError")
                    return
                }

                $(el).removeClass("XValidateError")
                $(el).val(value)

            } else {
                $(el).addClass("XValidateError")
                return
            }      
        } else {
            $(el).removeClass("XValidateError")
        }
    })
}

$(document).ready(function() {

    /** http://be.twixt.us/jquery/formSubmission.php */
    $.fn.ajaxSubmit = function(callBackFunction, filterFunction) { /* Change a form's submission type to ajax */
        this.submit(function(){
            var params = []
            try {
                /** find form elements */
                $(this).find(":hidden, :checked, :checkbox, :disabled, :enabled, :file, :image, :input, :password, :radio, :reset, :selected, :submit, :text, :input[type=hidden]").each(function() {
                    if (filterFunction(this)) {
                        if($(this).attr("name")) {
                
                            if (this.name != "") {

                                /** value for chekced */
                                if($(this).attr("type") == "checkbox" || $(this).attr("type") == "radio") {
                                    if($(this).attr("checked")) {
                                        val = "1"
                                    } else {
                                        val = ""
                                    }
                                } else {
                                    val = this.value
                                }

                                if(typeof(params[this.name]) == "undefined") {
                                    params[this.name] = [val];
                                } else {
                                    params[this.name].push(val)
                                }
                  
                            }
                        }
                    }
                });

                /** build string */
                paramsStr = ""
                for(key in params) {
                    if(params[key].length == 1) {
                        paramsStr = paramsStr + "&" + key + "=" + params[key]
                    } else {
                        paramsStr = paramsStr + "&" + key + "=" + params[key].join("&" + key + "=")
                    }
                }

                $.post(this.getAttribute("action"), paramsStr, function(data){
                    callBackFunction(data)
                });
            } catch(e) {
         
                return false
            }
            return false;
        });
        return this;
    }

    /** init XServerRequest elements */
    $(".XServerRequest").each(function() {
        XServerRequestElementInit($(this));
    });

    /** init XServerAjaxRequest elements */
    $(".XServerAjaxRequest").each(function() {
        XServerAjaxRequestElementInit($(this));
    });

    /** init XAction elements */
    $(".XAction").each(function() {
        XActionElementInit($(this));
    });

    /** add draggable for XDraggable elements */
    $(".XDraggable").draggable({
        opacity: 0.65,
        helper: 'clone'
    });

    /** add droppable for XDroppable elements */
    $(".XDroppable").droppable({
        accept: function (e) {
            return e.is($(this).attr('XDroppableAccept'));
        },
        hoverClass: 'ui-droppable-hover',
        drop: function(event, ui) {

            $(ui.helper).remove()

            /** ask user to confirm request */
            var userconfirm = $(this).attr('XActionConfirm');
            if(''!=userconfirm && !confirm(userconfirm)) return;

            /** perform server request */
            var url = $(this).attr('XDroppableServerAction');
            var result = '';
            if (''!=url) {
                result = ServerAjaxRequest(SERVICE_DIRECTORY + url + ui.draggable.attr('XDraggableServerAction'));
                if (result!='' && result==false) return;
            }

            /** do callback action */
            var fname = $(this).attr('XDroppableServerResponseCB');
            if (''!=fname) {
                var f = eval(fname);
                f(result, $(this), ui.draggable);
            }
        }
    });

    /** initialize XValidate elements */
    $(".XValidate").each(function() {
        var validate_function = eval("XValidate" + $(this).attr("XValidateType"));
        validate_function($(this));
    });

    /** initialize XSel list selectors */
    $(".XSel").each(function() {
        $(this).css('cursor', 'pointer');
        $(this).click(function() {
            name = $(this).attr('XSelName')
            attr = $(this).attr('XSelAttr')
            val = $(this).attr('XSelAttrVal')
            $(this).parents("form").find("input[name='"+name+"']").each(function() {
                if ($(this).attr(attr) == val)
                    $(this).attr('checked', true)
                else
                    $(this).attr('checked', false)
            })
        })
    })
});


/** from the net */


function urlEncodeCharacter(c) {
    return '%' + c.charCodeAt(0).toString(16)
}

function urlDecodeCharacter(str, c) {
    return String.fromCharCode(parseInt(c, 16))
}

function urlEncode( s ) {
    return encodeURIComponent( s ).replace( /\%20/g, '+' ).replace( /[!'()*~]/g, urlEncodeCharacter )
}

function urlDecode( s ) {
    return decodeURIComponent(s.replace( /\+/g, '%20' )).replace( /\%([0-9a-f]{2})/g, urlDecodeCharacter)
}

