// *This file was Modified by Rob Gravelle (Vizimetrics, Inc) in January 2009 to use MooTools instead of Prototype.
// *All modified code is released under the LGPL, Copyright 2009 Vizimetrics, Inc.  <tim@vizimetrics.com>

function loadMootools(url)
{
	if (window.MooTools === undefined)
	{
		document.write('<script src="', url, '" type="text/JavaScript"><\/script>');
	}
}

function initScripts()
{
	if (window.MooTools === undefined) return;
	
	//The escapeHTML and unescapeHTML functions are not available in MooTools.
	String.prototype.unescapeHTML = function unescapeHTML() 
	{ 
		return this.replace( 
			/&(amp|[lg]t|quot);/g, 
			function(m, p1) 
			{ 
				var map = { 
				  amp:  "&", 
				  lt:   "<", 
				  gt:   ">", 
				  quot: '"' 
				}; 
	
				return map[p1]; 
			}
		); 
	} 
	
	String.prototype.escapeHTML = function() 
	{
		var div = document.createElement('div');
		var text = document.createTextNode('');
		div.appendChild(text);
		text.data = this;
	
		return  div.innerHTML;
	}
	
	//using Mootools Array.filter()
	window.without = function(array, value)
	{
	  	return array.filter(function(item, index) { return item != value; });
	}

	window.$inspect = function(obj)
	{
		if ( $type(obj) )
		{
			var value, props = '';
			
			for (var prop in obj)
			{
				switch ($type(obj[prop]))
				{
					case 'function':
						value = prop + ': function' + '\n';
						break;
					
					case 'object':
						value = prop + '(object): ' + $inspect(obj[prop]);
						break;
					
					default:
						value = prop + ':' + String(obj[prop]) + '\n';
						break;
				}
				props += value;
			}
			
			return props;
		}
		else
		{
			return String(obj);
		}
	}
	
	window.trace = alert;
	
	if (( MooTools.version == '1.11')||( MooTools.version == '1.12'))
	{	//alert('Mootools 1.11 / 1.12 detected.');
		
		window.$type = function(obj){
		    if (obj == undefined) return false;
		    if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
		    if (obj.nodeName){
		        switch (obj.nodeType){
		            case 1: return 'element';
		            case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
		        }
		    } else if (typeof obj.length == 'number'){
		        if (obj.callee) return 'arguments';
		        else if (obj.item) return 'collection';
		    }
		    return typeof obj;
		};
		
		function $unlink(object){
		    var unlinked;
		    switch ($type(object)){
		        case 'object':
		            unlinked = {};
		            for (var p in object) unlinked[p] = $unlink(object[p]);
		        break;
		        case 'hash':
		            unlinked = new Hash(object);
		        break;
		        case 'array':
		            unlinked = [];
		            for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
		        break;
		        default: return object;
		    }
		    return unlinked;
		};
		
		$extend( Cookie, {
				write: function(key, value, options) { return Cookie.set(key, value, options); }
		});
		
		$extend( Cookie, {
				read: function(key) { return Cookie.get(key); }
		});
		
		$extend( Cookie, {
				dispose: function(key, options) { return Cookie.remove(key, options); }
		});
		
		//Ajax Request
		window.Request = Ajax.extend({
		    initialize: function(options)
		    {
		        this.parent(options.url, options);
		    },
		    send: function(data) 
		    {
		        data = data || this.options.data;
		        switch($type(data))
		        {
		            case 'element': data = $(data).toQueryString(); break;
		            case 'object': data = Object.toQueryString(data);
		        }
		        if (this._method) data = (data) ? [this._method, data].join('&') : this._method;
		
		        return this.parent(this.url, data);
		    }
		});
		
		Element.extend({
		    destroy: function() {
		        Element.empty(this);
		        Element.dispose(this);
		
		        return null;
		    },
		    empty: function() {
		        $A(this.childNodes).each(function(node, index){
		            Element.destroy(node);
		        });
		        return this;
		    },
		    dispose: function() {
		        return Element.remove(this);
		    },
		    set: function(prop, value){
		        switch ($type(prop)){
		            case 'object':
		                for (var p in prop) this.set(p, prop[p]);
		                break;
		            case 'string':
		                switch(prop) {
		                    case 'styles': this.setStyles(value); break;
		                    case 'events': if (this.addEvents) this.addEvents(value); break;
		                    case 'properties': this.setProperties(value); break;
		                    default: this.setProperty(prop, value);
		                }
		        }
		        return this;
		    }   
		});
		    
		var Native = function(options){
		    options = options || {};
		    var name = options.name;
		    var legacy = options.legacy;
		    var protect = options.protect;
		    var methods = options.implement;
		    var generics = options.generics;
		    var initialize = options.initialize;
		    var afterImplement = options.afterImplement || function(){};
		    var object = initialize || legacy;
		    generics = generics !== false;
		
		    object.constructor = Native;
		    object.$family = {name: 'native'};
		    if (legacy && initialize) object.prototype = legacy.prototype;
		    object.prototype.constructor = object;
		
		    if (name){
		        var family = name.toLowerCase();
		        object.prototype.$family = {name: family};
		        Native.typize(object, family);
		    }
		
		    var add = function(obj, name, method, force){
		        if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
		        if (generics) Native.genericize(obj, name, protect);
		        afterImplement.call(obj, name, method);
		        return obj;
		    };
		
		    object.alias = function(a1, a2, a3){
		        if (typeof a1 == 'string'){
		            if ((a1 = this.prototype[a1])) return add(this, a2, a1, a3);
		        }
		        for (var a in a1) this.alias(a, a1[a], a2);
		        return this;
		    };
		
		    object.implement = function(a1, a2, a3){
		        if (typeof a1 == 'string') return add(this, a1, a2, a3);
		        for (var p in a1) add(this, p, a1[p], a2);
		        return this;
		    };
		
		    if (methods) object.implement(methods);
		
		    return object;
		};
		
		Native.genericize = function(object, property, check){
		    if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
		        var args = Array.prototype.slice.call(arguments);
		        return object.prototype[property].apply(args.shift(), args);
		    };
		};
		
		Native.implement = function(objects, properties){
		    for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
		};
		
		Native.typize = function(object, family){
		    if (!object.type) object.type = function(item){
		        return ($type(item) === family);
		    };
		};
		
		(function(){
		    var natives = {'Array': Array, 'Date': Date, 'Function': Function, 'Number': Number, 'RegExp': RegExp, 'String': String};
		    for (var n in natives) new Native({name: n, initialize: natives[n], protect: true});
		
		    var types = {'boolean': Boolean, 'native': Native, 'object': Object};
		    for (var t in types) Native.typize(types[t], t);
		
		    var generics = {
		        'Array': ["concat", "indexOf", "join", "lastIndexOf", "pop", "push", "reverse", "shift", "slice", "sort", "splice", "toString", "unshift", "valueOf"],
		        'String': ["charAt", "charCodeAt", "concat", "indexOf", "lastIndexOf", "match", "replace", "search", "slice", "split", "substr", "substring", "toLowerCase", "toUpperCase", "valueOf"]
		    };
		    for (var g in generics){
		        for (var i = generics[g].length; i--;) Native.genericize(window[g], generics[g][i], true);
		    };
		})();
		
		window.Hash = new Native({
		
		    name: 'Hash',
		
		    initialize: function(object){
		        if ($type(object) == 'hash') object = $unlink(object.getClean());
		        for (var key in object) this[key] = object[key];
		        return this;
		    }
		
		});
		
		Hash.implement({
		
		    forEach: function(fn, bind){
		        for (var key in this){
		            if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
		        }
		    },
		
		    getClean: function(){
		        var clean = {};
		        for (var key in this){
		            if (this.hasOwnProperty(key)) clean[key] = this[key];
		        }
		        return clean;
		    },
		
		    getLength: function(){
		        var length = 0;
		        for (var key in this){
		            if (this.hasOwnProperty(key)) length++;
		        }
		        return length;
		    }
		
		});
		
		Hash.alias('forEach', 'each');
		
		Hash.implement({
		
		    has: Object.prototype.hasOwnProperty,
		
		    keyOf: function(value){
		        for (var key in this){
		            if (this.hasOwnProperty(key) && this[key] === value) return key;
		        }
		        return null;
		    },
		
		    hasValue: function(value){
		        return (Hash.keyOf(this, value) !== null);
		    },
		
		    extend: function(properties){
		        Hash.each(properties, function(value, key){
		            Hash.set(this, key, value);
		        }, this);
		        return this;
		    },
		
		    combine: function(properties){
		        Hash.each(properties, function(value, key){
		            Hash.include(this, key, value);
		        }, this);
		        return this;
		    },
		
		    erase: function(key){
		        if (this.hasOwnProperty(key)) delete this[key];
		        return this;
		    },
		
		    get: function(key){
		        return (this.hasOwnProperty(key)) ? this[key] : null;
		    },
		
		    set: function(key, value){
		        if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
		        return this;
		    },
		
		    empty: function(){
		        Hash.each(this, function(value, key){
		            delete this[key];
		        }, this);
		        return this;
		    },
		
		    include: function(key, value){
		        var k = this[key];
		        if (k == undefined) this[key] = value;
		        return this;
		    },
		
		    map: function(fn, bind){
		        var results = new Hash;
		        Hash.each(this, function(value, key){
		            results.set(key, fn.call(bind, value, key, this));
		        }, this);
		        return results;
		    },
		
		    filter: function(fn, bind){
		        var results = new Hash;
		        Hash.each(this, function(value, key){
		            if (fn.call(bind, value, key, this)) results.set(key, value);
		        }, this);
		        return results;
		    },
		
		    every: function(fn, bind){
		        for (var key in this){
		            if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
		        }
		        return true;
		    },
		
		    some: function(fn, bind){
		        for (var key in this){
		            if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
		        }
		        return false;
		    },
		
		    getKeys: function(){
		        var keys = [];
		        Hash.each(this, function(value, key){
		            keys.push(key);
		        });
		        return keys;
		    },
		
		    getValues: function(){
		        var values = [];
		        Hash.each(this, function(value){
		            values.push(value);
		        });
		        return values;
		    },
		
		    toQueryString: function(base){
		        var queryString = [];
		        Hash.each(this, function(value, key){
		            if (base) key = base + '[' + key + ']';
		            var result;
		            switch ($type(value)){
		                case 'object': result = Hash.toQueryString(value, key); break;
		                case 'array':
		                    var qs = {};
		                    value.each(function(val, i){
		                        qs[i] = val;
		                    });
		                    result = Hash.toQueryString(qs, key);
		                break;
		                default: result = key + '=' + encodeURIComponent(value);
		            }
		            if (value != undefined) queryString.push(result);
		        });
		
		        return queryString.join('&');
		    }
		
		});
		
		Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
	}
}



