﻿// This is just here to tell JS lint that we need to use a global variable
/*global TVI , document, alert, console, window $ */

/// Declare Namespace

TVI = { version: "0.2" };

// Create function for applying config options to classes
TVI.apply = function(o, c, d){

    // o = object   : The object that is having stuff applied to it.
    // c = config   : The config options that will be applied to the object
    // d = defaults : Any default options that
    
    // See if defaults have been supplied
    if (d) {
        // If they have then call the apply function again with the defaults as the config
        TVI.apply(o, d);
    }

    // Check the object and config are valid objects
    if (o && c && typeof c == 'object') {
        // Loop through the config and add all the properties and methods
        for (var p in c) {
			// Check that we're only dealing with config members, not stuff inherited through the prototype
            if (c.hasOwnProperty(p) && c[p] !== undefined) {
		        o[p] = c[p];
		    }
        }
    }
	
    // Return the original object
    return o;
};


// Closed function - is not global but is instantiated and run immediately
(function() {

        // ********** Set up TVI variable and methods ********** //

        TVI.apply(TVI, {

            /**
            * Counter for creating uniqu ID's for components.
            * @property
            * @type integer
            */
            idSeed: 0,

            /**
            * Function for creating a unique ID for any control
            * @property
            * @type Function
            */
            createID: function(o, prefix) {
                prefix = prefix || "TVI-auto-";
                if (o.id === undefined || o.id === null || o.id === '') {
                    var id = prefix + (++this.idSeed);
                    o.id = id;
                }
                return o;
            },

            /**
            * A reusable empty function
            * @property
            * @type Function
            */
            emptyFn: function() { },

            /**
            * List of field types used in forms
            * @property
            * @type Array
            */
            fieldTypes: [
		        'textBox',
		        'textArea',
		        'dropDownList',
		        'checkBox',
			    'password',
			    'multiRadio',
			    'multiCheckBox'
		    ],

            /**
            * List of allowed data types when communicating with a database
            * @property
            * @type Array
            */
            dataTypes: [
			    'varchar',
			    'text',
			    'boolean',
			    'integer',
			    'decimal',
			    'date'
		    ],

            /**
            * Ajax - wraps up the jQuery Ajax function and adds defaults
            */
            ajax: function(params) {

                // Defaults for ajax calls
                var defaults = {
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    data: '{}'
                }

                var successFunction = params.success;
                var failureFunction = params.failure;

                // Overwrite the default parameters with the ones passed in
                var ajaxParams = TVI.apply(defaults, params);

                // Intercept the success function and add some functionality
                ajaxParams.success = function(data) {

                    // Parse the response
                    var response = JSON.parse(data.d);

                    // Check that the call was successful
                    if (response.success === true) {

                        // Run the success function if it exists
                        if (successFunction) {
                            successFunction.call(this, response);
                        }
                    }
                    else {
                        // Run the failure function if it exists
                        TVI.logError(response);
                        if (failureFunction) {
                            failureFunction.call(this, response);
                        }
                    }

                }

                // Intercept the error function and pass it through to the default ajax error function.
                ajaxParams.error = function() {

                    var errorCode = params.errorCode || '010004';
                    var errorMessage = params.errorMessage || 'Error occured during Ajax call';

                    // Log the error to the console
                    TVI.logError({
                        "code": errorCode,
                        "message": errorMessage
                    });

                    // Run the error function if it exists
                    if (params.error !== undefined && params.error !== null) {
                        params.error.call();
                    }
                };

                // Make the ajax call
                $.ajax(ajaxParams);

            },

            /**
            * Check to see if the Firebug console exists for error logging
            */
            firebugCheck: function() {

                // Attempt top initialise the console if it doesn't exist
                if (typeof console == 'undefined') {
                    if (typeof loadFirebugConsole == 'function') {
                        loadFirebugConsole();
                    }
                }

                // Now check to see if the console exists
                if ($.browser.mozilla && window.console !== null && window.console !== undefined) {
                    return true;
                }
                else {
                    return false;
                }
            },

            /**
            * Log an error to the Firebug console.
            * @param {Object} errorObject - An object containing an error code and error message.
            */
            logError: function(errorObject) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {

                    // Check to see if there is an errors colleciton
                    if (errorObject.errors) {

                        // Loop through
                        var errorsLength = errorObject.errors.length;
                        for (i = 0; i < errorsLength; i++) {
                            console.error('TVI Error: ' + errorObject.errors[i].code + ' - ' + errorObject.errors[i].message);
                        }
                    }
                    else {
                        console.error('TVI Error: ' + errorObject.code + ' - ' + errorObject.message);
                    }

                }
            },

            /**
            * Log a warning to the Firebug error console.
            * @param {string} warning - The warning to be shown
            */
            logWarning: function(warning) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.warn(warning);
                }
            },

            /**
            * Log a comment to the Firebug console.
            * @param {string} comment - The comment to show
            */
            logComment: function(comment) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.info(comment);
                }
            },

            /**
            * Wraps up Firebug's console.dir function.
            * @param {Object} o - The object to bad added to the console
            */
            logDir: function(o) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.dir(o);
                }
            },

            /**
            * Start a timer in Firebug's console.
            * @param {string} name - The name of the timer. Must match the logTimerEnd name.
            */
            logTimer: function(name) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.time(name);
                }
            },

            /**
            * Stops a timer in Firebug's console.
            * @param {string} name - The name of the timer. Must match the start timer name.
            */
            logTimerEnd: function(name) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.timeEnd(name);
                }
            },

            /**
            * Starts a group of nested comments/warnings/errors in Firebug's console.
            * @param {string} name - The name of the group. Must match the logGroupEnd name.
            */
            logGroup: function(name) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.group(name);
                }
            },

            /**
            * Ends a group of nested comments/warnings/errors in Firebug's console.
            * @param {string} name - The name of the group. Must match the start name.
            */
            logGroupEnd: function(name) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.groupEnd(name);
                }
            },

            /**
            * Starts Firebug's profiler.
            * @param {string} title - Optional title for the profiler report.
            */
            logProfile: function(title) {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.profile(title);
                }
            },

            /**
            * Stops Firebug's profiler.
            */
            logProfileEnd: function() {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.profileEnd();
                }
            },

            /**
            * Prints an interactive stack trace of JavaScript execution at the point where it is called.
            */
            logTrace: function() {

                // Console only exists in Firebug so check it exists before trying to write to it
                if (TVI.firebugCheck() === true) {
                    console.trace();
                }
            }

        });

    })();



// ********** TVI UTIL ********** //
TVI.util = {};

TVI.apply(TVI.util, {
	
	/**
     * Adds a new option to a select element.
     * @param {Object} e - the select element we are adding the option to.
     * @param {String} v - the value of the option we want to add.
     * @param {String} t - the text of the option we want to add.
     */
	addSelectOption: function(e, v, t){
		var option = document.createElement("option");
	    option.value = v;
	    
		// Set the text to the same as the value if it hasn't been supplied
		if(t === null || t === "" || t === undefined){
			option.text = v;
		}
		else{
			option.text = t;
		}
	
	    // get current options
	    var o = e.options;
	
	    // get number of options
	    var oL = o.length;
	
	    if (!e.cache) {
	        e.cache = {};
	        // loop through existing options, adding to cache
	        for (var l = 0; l < oL; l++) {
	            e.cache[o[l].value] = l;
	        }
	    }
	
	    // add to cache if it isn't already
	    if (typeof e.cache[v] == "undefined") {
	        e.cache[v] = oL;
	    }
	    e.options[e.cache[v]] = option;
	},
	
	/**
     * Selects an item in the jQuery Select list based on it's value.
     * @param {Object} e - the select element we are adding the option to.
     * @param {String} v - the value of the option we want to select.
     */
	selectOption: function(e, v){
		
		// Find the select list
		e.each(function(){

			// Shortcut to options and length of the options
			o = this.options;
			optionsLength = this.options.length;
			
			// Loop through all the options
			for (var i = 0; i < optionsLength; i++) {
				
				// If the option matches then select it
				if(o[i].value == v){
					o[i].selected = true;
				}

			}
		});

	},
	
	
	/**
     * Returns the text of the selected item in the select list passed in
     * @param {Object} e - the jQuery select element we are adding the option to.
     */
	getSelectedOptionText: function(e){
		
		return e[0].options[e[0].selectedIndex].text;
	},
	
	
	/**
     * converts all special characters in a string to HTML entities and returns the string
     * @param {Object} s - the string to entitify.
     */
	stringToEntities: function(s){
		
		return $('<div/>').text(s).html().replace('"',"&quot;");
	},
	
	/**
     * converts all HTML entities in a string to original characters and returns the string
     * @param {Object} s - the string to deEntitify.
     */
	stringFromEntities: function(s){
		
		$('#temp').html(s);
		return $('#temp').html();
	},
	
	/**
     * converts all quotes in a string to their ascii code equivelants
     * @param {Object} s - the string to encode.
     */
	encodeQuotes: function(s){
		
		var output = s;
		s = s.replace(/"/g,'&#34;');
		s = s.replace(/'/g,'&#39;');
		return s;
	},
	
	/**
     * converts all ascii quote codes in a string back into quotes
     * @param {Object} s - the string to encode.
     */
	decodeQuotes: function(s){
		
		var output = s;
		s = s.replace(/&#34;/g,'"');
		s = s.replace(/&#39;/g,"'");
		return s;
	}

	
}); // End of TVI.util



// ***************************************************************** //
// ******** Override and extend default objects and methods ******** //
// ***************************************************************** //

// Add an Array.indexOf method to IE
if(!Array.indexOf){
	Array.prototype.indexOf = function(obj){
		var L = this.length;
			for(var i=0; i<L; i++){
				if(this[i]==obj){
				return i;
			}
		}
		return -1;
	};
}

// Adds a Trim() method to strings
String.prototype.trim = function() { 
    return this.replace(/^\s+|\s+$/g, '');
};



