// Global variables
// Dummy function used as the default when callbacks are not supplied
var g_fDummyFunction = function() { var b = 1; };

$ = jQuery;
// API Functionality
function API(methodName, callbackFunction, JSONparameters) {
	/// <summary>Makes an AJAX call to a web service and gets the results</summary>
    /// <param name="methodName">the name of the web service method to call</param>
    /// <param name="isPost">[Optional] Indicates if the request should be a POST request, instead of a GET request</param>
    /// <param name="callbackFunction">[Optional] The JS callback function after the attempt is successful</param>
    /// <param name="JSONparameters">[Optional] JSON parameters to pass with the web service call</param>
	
	// Parameter validity check
    if (!methodName) { return; }

    // Get the callback function and parameters
    var fCallback = null;
    if (arguments.length > 1 && arguments[1]) { fCallback = arguments[1]; }
    else { fCallback = g_fDummyFunction; }

    var objJSONparameters = "{}";
    if (arguments.length > 2 && arguments[2]) { objJSONparameters = arguments[2]; }

    var szURL = 'apps.caltrend.com/widgets/api/widget.svc/' + methodName;
    var bSecure = szURL.indexOf('https') >= 0 || (szURL.indexOf('http') < 0 && ("https:" == document.location.protocol));
	if (bSecure) {
		szURL = 'https://' + szURL;
	} else {
		szURL = 'http://' + szURL;
	}

    $.ajax({
        type: 'GET',
        contentType: 'application/json; charset=utf-8',
        secureuri: bSecure,
        url: szURL,
        data: objJSONparameters,
        dataType: 'jsonp',
        success: fCallback,
		cache: false
    });
}

function Forms_AddHandlers(parent) {
    /// <summary>Adds formfield and validate event handlers to a form</summary>
    /// <param name="parent">the jQuery selector/object to use to find elements to add handlers to</param>

    // Validity check
    if (!parent) { return; }	

    // Add validate event handlers
    objParent.find('select.validate').change(function () { Validate(this); });
    objParent.find('input.validate').filter('[type=checkbox]').change(function () { Validate(this); });
    objParent.find('input.validate').filter('[type!=checkbox]').blur(function () { Validate(this); });

    // Handle 'Enter' key presses by clicking the first button
    objParent.find('input[type=text],input[type=password]').keydown(function (event) {
        // track enter key
        var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode));
        if (keycode == 13) { // keycode for enter key
            // force the 'Enter Key' to implicitly click the Update button
            var objThis = $(this), objButton = null, nTries = 0;
            do {
                objButton = objThis.find('input[type=button],input[type=submit],input[type=image],a.formbtn').filter(':visible');
                objThis = objThis.parent();
            } while (objButton.length == 0 && nTries < 4);
            if (objButton.length > 0) {
                objButton.trigger('click');
            }
            return false;
        } else {
            return true;
        }
    });

    // Remove unwanted focus lines when links are clicked
    objParent.find("a").each(function () {
        var fCallback = function () {
            // Remove the focus outline
            if (this.blur) { this.blur(); } // most browsers 
            if (this.hideFocus) { this.hideFocus = true; } // internet explorer
            if (this.style) { this.style.outline = 'none'; }  // mozilla
        }
        var objThis = $(this);
        objThis.mouseup(fCallback);
        objThis.mousedown(fCallback);
    });
}

// -------------- Validation Functions ------------- //
function Validate(object, validateChildren) {
    /// <summary>Validates an object, and optionally its children as well</summary>
    /// <param name="object">The jQuery selector for the object to validate</param>
    /// <param name="validateChildren">Indicates if child input fields should also be validated</param>

    // Validity check
    if (!object) { return true; }

    // Ensure the object is valid
    var objToValidate = $(object);
    if (objToValidate.length == 0) { return false; }

    // Check if we are validiting a single item
    if (arguments.length < 2 || !arguments[1]) {
        var bReturn = true; // return value

        objToValidate.each(function () {
            var bSubValid = true; // checks if the object in the each function is valid
            var bIsValidType = true; // indicates if the element is one that we will process for validation
            var objSub = $(this);

            // Validate the single item
            switch (this.tagName.toUpperCase()) {
                case 'SELECT':
                    bSubValid = this.selectedIndex > 0;
                    break;
                case 'INPUT':
                    if (objSub.attr('type').toUpperCase() == 'CHECKBOX') {
                        bSubValid = objSub.is(':checked');
                    } else {
                        var szVal = objSub.val();
                        if (objSub.is('.formfield') && objSub.attr('title')) {
                            szVal = szVal.replace(objSub.attr('title'), '');
                        }
                        if (objSub.is('.integer')) {
                            if (!parseInt(szVal, 10) || parseInt(szVal, 10) < 1) { bSubValid = false; }
                            else { bSubValid = true; }
                        } else if (objSub.is('.number')) {
                            if (!parseFloat(szVal) || parseFloat(szVal) < 1) { bSubValid = false; }
                            else { bSubValid = true; }
                        } else { bSubValid = szVal && szVal.length > 0; }
                    }
                    break;
                case 'TEXTAREA':
                    // Normal text area
                    if (objSub.is(':not(.tinymce)') || !tinyMCE) {
                        bSubValid = objSub.is(':not(:empty)');
                    } else {
                        // TinyMCE text area
                        var objTinyMCE = tinyMCE.get(objSub.attr('id'));
                        if (!objTinyMCE) {
                            bSubValid = objSub.is(':not(:empty)');
                        } else {
                            var szMceContent = objTinyMCE.getContent();
                            bSubValid = szMceContent && szMceContent.length > 0;

                            // We do not get a blur event from tinyMCE, so add a keypress
                            //      event handle to remove the validation message
                            var fKeyPress = function (ed, e) {
                                objTinyMCE.onKeyUp.remove(fKeyPress);
                                setTimeout(function () { Validate(objSub); }, 100);
                            };
                            if (!bSubValid) {
                                objTinyMCE.onKeyUp.add(fKeyPress);
                            }
                        }
                    }
                    break;
                default:
                    bSubValid = true;
                    bIsValidType = false;
                    break;
            }

            // Hide/show the element
            if (bIsValidType) {
                if (bSubValid) {
                    objSub.each(function () {
                        var objErrorMessage = $('#' + this.id + '-rfv');
                        if (objErrorMessage.length == 0) {
                            objErrorMessage = $('.' + $(this).attr('name') + '-rfv', $(this).parent().parent());
                        }
                        objErrorMessage.addClass('none');
                    });
                } else {
                    objSub.each(function () {
                        var objErrorMessage = $('#' + this.id + '-rfv');
                        if (objErrorMessage.length == 0) {
                            objErrorMessage = $('.' + $(this).attr('name') + '-rfv', $(this).parent().parent());
                        }
                        objErrorMessage.removeClass('none');
                    });
                    bReturn = false;
                }
            }
        });

        // All set
        return bReturn;
    } else {
        // Get all the child input fields
        var objFormInputs = objToValidate.find('.validate:visible:not(.none)');
        var bValid = true;
        objFormInputs.each(function () {
            if (!Validate(this)) {
                bValid = false;
                // we don't return false because we always want to validate the entire form
            }
        });

        return bValid;
    }
}
function ValidateHideMessage(object, hideChidlren) {
    /// <summary>Resets all validation messages back to a hidden state for an object, and optionally its children as well</summary>
    /// <param name="object">The jQuery selector for the object to validate</param>
    /// <param name="hideChildren">Indicates if child input fields should also have validation messages hidden</param>

    // Validity check
    if (!object) { return; }

    // Ensure the object is valid
    var objToValidate = $(object);
    if (objToValidate.length == 0) { return; }

    // Check if we are validiting a single item
    if (arguments.length < 2 || !arguments[1]) {
        objToValidate.each(function () {
            var objSub = $(this);

            // Reset all corresponding messages
            objSub.each(function () {
                var objErrorMessage = $('#' + this.id + '-rfv');
                if (objErrorMessage.length == 0) {
                    objErrorMessage = $('.' + $(this).attr('name') + '-rfv', $(this).parent().parent());
                }
                objErrorMessage.addClass('none').removeAttr('style');
            });
        });
    } else {
        // Get all the child input fields
        var objFormInputs = objToValidate.find('.validate');
        objFormInputs.each(function () {
            ValidateHideMessage(this);
        });
    }
}

/**
* JSON plugin
* http://code.google.com/p/jquery-json/downloads/list
*/
(function($) {
	function toIntegersAtLease(n)
	{ return n < 10 ? '0' + n : n; }
	Date.prototype.toJSON = function(date) {
		return this.getUTCFullYear() + '-' +
toIntegersAtLease(this.getUTCMonth()) + '-' +
toIntegersAtLease(this.getUTCDate());
	}; var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g; var meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }; $.quoteString = function(string) {
		if (escapeable.test(string)) {
			return '"' + string.replace(escapeable, function(a) {
				var c = meta[a]; if (typeof c === 'string') { return c; }
				c = a.charCodeAt(); return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
			}) + '"';
		}
		return '"' + string + '"';
	}; $.toJSON = function(o, compact) {
		var type = typeof (o); if (type == "undefined")
			return "undefined"; else if (type == "number" || type == "boolean")
			return o + ""; else if (o === null)
			return "null"; if (type == "string")
		{ return $.quoteString(o); }
		if (type == "object" && typeof o.toJSON == "function")
			return o.toJSON(compact); if (type != "function" && typeof (o.length) == "number") {
			var ret = []; for (var i = 0; i < o.length; i++) { ret.push($.toJSON(o[i], compact)); }
			if (compact)
				return "[" + ret.join(",") + "]"; else
				return "[" + ret.join(", ") + "]";
		}
		if (type == "function") { throw new TypeError("Unable to convert object of type 'function' to json."); }
		var ret = []; for (var k in o) {
			var name; type = typeof (k); if (type == "number")
				name = '"' + k + '"'; else if (type == "string")
				name = $.quoteString(k); else
				continue; var val = $.toJSON(o[k], compact); if (typeof (val) != "string") { continue; }
			if (compact)
				ret.push(name + ":" + val); else
				ret.push(name + ": " + val);
		}
		return "{" + ret.join(", ") + "}";
	}; $.compactJSON = function(o)
	{ return $.toJSON(o, true); }; $.evalJSON = function(src)
	{ return eval("(" + src + ")"); }; $.secureEvalJSON = function(src) {
		var filtered = src; filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@'); filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); if (/^[\],:{}\s]*$/.test(filtered))
			return eval("(" + src + ")"); else
			throw new SyntaxError("Error parsing JSON, source is not valid.");
	};
})(jQuery);
