// General Igloo JS document £

//Logging function 
var Igloo = {init:function(){

	this.log = function() {
		if(window.console) window.console.log( Array.prototype.slice.call(arguments) );
	}
	
	this.isIn = function(arr,name,value){
		for(var i in arr) {
			if(arr[i][name] === value) return i;
		}
		return false;
	}
	
	this.append = function(a,b){
		var c = [];
		for (var i = 0, mx = a.length; i < mx; i++) c.push(a[i]);
		for (var i = 0, mx = b.length; i < mx; i++) c.push(b[i]);
		return c;
	}
	
	this.delegate = function(){
		var a = [];
		var f = arguments[0];
		for(var i = 1; i < arguments.length; i++) a.push(arguments[i]);
		return function(){var b = Igloo.append(arguments,a);f.apply(this,b);}
	}
	
}}; Igloo.init();

//_________________________________________________________________________//

//Speed tester
//V1-01 - 13/01/2011
//Call LoadSpeed.imageTest(image src, size in bytes, on complete function)

var LoadSpeed = {init:function() {
	var _this = this;

	//Settings
	this.no_cache = true;
	this.wait_for_site = true;	

	//Vars
	this.src;
	this.size;
	this.t1;
	this.t2;
	this.time;
	this.speed;
	this.onComplete;
	
	this.img = new Image();
	this.img.onload = function(){_this._onImageLoad()} //function wrapper otherwise onImageLoad wont be ready
	this.img.onerror = function(){_this._onImageError()} //function wrapper otherwise onImageLoad wont be ready


	//public functions
	this.imageTest = function(src,size,onComplete) {
		
		//We wait until everything on the page is loaded before attempting speed test
		if(this.img.src) return false;
		
		if(this.wait_for_site) $(document).ready(this._imageTest.call(this,src,size,onComplete));
		else this._imageTest(src,size,onComplete);
	}
	
	this.getSpeed = function(){
		if(!this.src) return false;
		if(!this.t2) return false;
		
		return this.speed;
	}
	
	//private functions
	this._imageTest = function(src,size,onComplete){
		var d = new Date();
		
		this.src = src;
		this.size = size;
		this.onComplete = onComplete;
		
		
		this.t1 = d.getTime();
		this.img.src = this.no_cache ? this._addCache(src) : src;		
	}
	
	this._onImageLoad = function() {
		var d = new Date();
		this.t2 = d.getTime();
		this.time = this.t2 - this.t1;
		this.speed = this.size / (this.time/1000) / 1024;
		if(this.onComplete) this.onComplete(this.img.src,this.getSpeed());
	}
	
	this._onImageError = function() {

	}		
	
	this._addCache = function(src) {
		var new_src,
			d = new Date();
			
		//Check for ?
		if(src.indexOf("?") == -1){
			new_src = src + "?" + d.getTime();
		}else{
			new_src = src + "&" + d.getTime();
		}
		
		return new_src;
	}
}}; LoadSpeed.init();




////// Preloader ////////
//V1-01 - 13/01/2011
//V1-02 - 14/01/2011 - added optional timing functions

var Preloader = {init:function() {
	var _this = this;
	
	this.speeds = [];
	
	this.images = [];
	this.state = "waiting";
	this.image_count = 0;
	this.load_count = 0;	
	
	this.listeners = [];
	
	this.img = new Image();
	this.img.onload = function(){_this._onImageLoad()} //function wrapper otherwise onImageLoad wont be ready
	this.img.onerror = function(){_this._onImageError()} //function wrapper otherwise onImageLoad wont be ready
	
	this.add = function(src,onComplete,extras){
		
		//If it's already in the list, call the reAdd function instead.
		if(Igloo.isIn(this.images,"src",src) !== false) return this.reAdd(src,onComplete);


		var id = this.images.length; 

		//Get the full scr for later comparison
		var full_src = "";
		if(src.substr(0,4) == "http") full_src = src;
		else if(src.substr(0,1) == "/") full_src = document.location.protocol + "//" + document.location.hostname + ( document.location.port ? ":"+document.location.port : "" ) + src;
		else{
			var parts = document.location.pathname.split("/");
			parts.pop();
			full_src = document.location.protocol + "//" + parts.join("/") + "/" + src; //Ports could cause a problem here...
		}
		
		
		this.images.push({src:src,id:id,status:"waiting",full_src:full_src,onComplete:[onComplete],errors:0});
		this.image_count ++;
		
		
		//Add extras
		if(extras && typeof(extras) == "object") {
			var image = this.images[this.images.length-1]; for (i in extras) image[i] = extras[i];
			if(extras['size']) this._startTimer(image);	
			if(extras['nocache']) image.full_src = this._addCache(image.full_src);
		}

		this._start();
		
		return id;
	}
	
	this.remove = function(src){
		var id = Igloo.isIn(this.images,"src",src);
		if(!id) return false;
		var image = this.images[id];
		if(image.status == "loading"){
			this.cancel();
		}
		if(image.status == "loaded" || image.status == "failed") this.load_count --;
		this.image_count --;
		this.images.splice(id,1);
		
		this.restart();
	}
	
	this.reAdd = function(src,onComplete){ //Note that extras are not updated.
		
		var id = Igloo.isIn(this.images,"src",src);
		var image = this.images[id];
		if(image.status == "loaded" || image.status == "failed"){
			onComplete.call(this,src,(image.status == "loaded"))
			this.callListeners(src,(image.status == "loaded"));
		}else{
			image.onComplete.push(onComplete);	
		}
		
		
	}
	
	this.restart = function(){
		if(this.state != "loading") this._start();
	}
	
	this.cancel = function(){
		var id = this.load_count;
		var image = this.images[id];
		
		if(this.state == "loading"){
			this.img.src = "";
			this.state = "waiting";
		}
		
		if(image) image.status = "waiting";
	}
	
	this.check = function(src){
		var id = Igloo.isIn(this.images,"src",src);
		
		if(id === false) return false;
		
		var image = this.images[id];

		return image.status;
	}
	
	
	
	//Private methods
	this._start = function(){
		var id = this.load_count;
		
		if(this.state == "loading") return true;
		if(this.image_count <= this.load_count) return true;
		
		
		this.state = "loading";
		this.images[id].status = "loading";		
		this.img.src = this.images[id].full_src

		
	}
	
	this._onImageLoad = function() {
		var full_src = this.img.src;

		this.state = "waiting";

		var id = Igloo.isIn(this.images,"full_src",full_src);
		
		if(!id){
			Igloo.log("Preload error: can't find "+ this.img.src);
			this._start();
			return false;
		}
		
		var image = this.images[id];
		
		image.status = "loaded";
		this.load_count++;		
		
		if(image.start_time) this._endTimer(image);
		
		for(var i in image.onComplete) if(image.onComplete[i]) image.onComplete[i](image.src,true,image);
		this.callListeners(image.src,true,image);
		
		if(this.image_count > this.load_count) this._start();
	}
	
	this._onImageError = function() {
		var full_src = this.img.src;
		
		this.state = "waiting";
		
		var id = Igloo.isIn(this.images,"full_src",full_src);
		
		if(!id){
			Igloo.log("Preload error: can't find "+ this.img.src);
			this._start();			
			return false;
		}
		
		var image = this.images[id];
		image.status = "waiting";
		image.errors ++;
		
		if(image.errors > 2){
			this.load_count++;
			image.status = "failed";
			for(var i in image.onComplete) if(image.onComplete[i]) image.onComplete[i](image.src,false,image);
			this.callListeners(image.src,false,image);			
		}
		
		
		
		this._start();
	}
	
	//Timer methods
	this.getSpeed = function(){
		var speed = 0;
		
		if(this.speeds.length == 0) return false;
		
		for(var i = 0; i < this.speeds.length; i++) {
			speed += this.speeds[i];
		}
		
		return speed / this.speeds.length ;
	}

	 this._startTimer = function(image){
		var d = new Date();
		image.start_time = d.getTime();
	 }
	 
	 this._endTimer = function(image){
		var d = new Date();
		image.end_time = d.getTime();
		image.total_time = image.end_time - image.start_time;
		image.speed = (image.size / 1024) / (image.total_time / 1000);
		
		//Check if we think it was cached
		if(image.speed > 1000 && !image.nocache ){
			image.was_cached = true;
		}else{
			image.was_cached = false;
		}
		
		if(!image.was_cached){
			this.speeds.push(image.speed);
		}
		
		Igloo.log(this.getSpeed());
	 }
	 
	 this._addCache = function(src) {
		var new_src,
			d = new Date();
			
		//Check for ?
		if(src.indexOf("?") == -1){
			new_src = src + "?" + d.getTime();
		}else{
			new_src = src + "&" + d.getTime();
		}
		
		return new_src;
	}
	
	//Standard listener methods
	this.addListener = function(f){
		this.listeners.push(f);
	}
	
	this.removeListener = function(f){
		for(var i in this.listeners){
			if(this.listeners[i] == f){
				this.listeners.splice(i,1); 
				return;
			}
		}
	}
	
	this.callListeners = function(){
		for(var i in this.listeners){
			this.listeners[i].apply(this,arguments);
		}
	}
	
}}; Preloader.init();


//----------------------------------------------------------//

//History class
//V1-01 - 13/01/2011

//We have settings for use history only, use history or hash, or none.
//History can store data for each state, but hash can't. We need an option for blank with data or blank without data

var Jhistory = {init: function(){

	this.settings = {
		useHistory:true,
		useSwfAddress:true
	}

	this.hasHistory = false;
	this.listeners = [];

	this.setup = function(){
		this.hasHistory = this.settings.useHistory && !(typeof history.pushState === 'undefined')
		if(this.hasHistory) {
			this.setupHTML5history();
		} else if(this.settings.useSwfAddress) {
			this.setupSwfAddress();
		}
	}
	
	this.setupHTML5history = function(){
		var _this = this;
		window.onpopstate = function(e){
			_this.onChange(e.state ? e.state : "");
		};
	}
	
	this.setupSwfAddress = function(){
		var _this = this;
		var fireChange = function(e){_this.onChange(e.value)}
		SWFAddress.addEventListener(SWFAddressEvent.CHANGE, fireChange);
	}
	
	this.onChange = function(v){
		
		//If the state is an object rather than just an address
		if(typeof(v) == "object"){
			v = v.data;	
		}
		
		if(v.substr(0,1) == "/") v = v.substr(1);
		
		
		//Get parts
		var parts = v.split('/');
		if(!parts) parts = [v];
		
		for(var i in this.listeners){
			this.listeners[i](parts);
		}
	}
		
	this.change = function(address,title,show){
		if(show == undefined) show = true;

		var state = address;
		if(address.substr(0,1) == "/") state = address.substr(1);
		
		if(this.hasHistory && !show){
			state = {address:'/',data:state}
			address = "/";
		}
		
		if(this.hasHistory){
			history.pushState(state, title ? title : address, address);
			this.onChange(state);
		}else{
			window.location.href = "#/" + state;
		}
		if(title) document.title = title
		return false; //Override default actions...
	}
	
	this.addListener = function(f){
		this.listeners.push(f);
	}
	
	this.removeListener = function(f){
		for(var i in this.listeners){
			if(this.listeners[i] == f){
				this.listeners.splice(i,1); 
				return;
			}
		}
	}
	
	this.setup();
}};
Jhistory.init();


//-------------------- JQUERY COOKIES -------------------------//

// JavaScript Document
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options = $.extend({}, options); // clone object since it's unexpected behavior if the expired property were changed
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
				date.setTime(date.getTime() + (options.expires*1000));
                //date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // NOTE Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '; path=/';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};

