/* Global */
Function.prototype.method = function (name, func) {
	if(!this.prototype[name]) {
		this.prototype[name] = func;
		return this;
	}
};

String.method('trim', function() {
	return this.replace(/^\s+|\s+$/g, '');
});

app = {
	html : {
		inlineIndicator : '<img src="../magazine/front/images/inline_indicator.gif" alt="Loading&hellip;" class="inlineIndicator"/>'
	},
	keys : {
		TAB : 9,
		ENTER : 13,
		ESC : 27
	},
	browser : {
		IE6 : false,
		IE7 : false,
		IE : false
	},
	helpers : {
		isKey : function(evt, key) {
			return evt.keyCode && evt.keyCode === key;
		},
		isValid : function(ok, msg) {
			return {valid: ok || false, msg: ok ? "Ok" : msg};
		}
	}
}

/* IE detection */
/*@cc_on
if (@_jscript_version == 5.7 && window.XMLHttpRequest)
 app.browser.IE7 = true;
else if (@_jscript_version == 5.6 || (@_jscript_version == 5.7 && !window.XMLHttpRequest))
 app.browser.IE6 = true;
app.browser.IE = true;
@*/

/* Steps class */
/************************************************************************/
app.chain = {
	steps : function(stepsArray) {
		var that = {},		
		all = [];
		
	    that.continueUntil = function() {
	        var i,j = 0;
	        
	        // Keep enabling until a test fails
	        // If test passes then enable next step
	        // step 1 is always enabled        
	        while (all[j].testAllRules() && j + 1 < all.length) {
	        	j += 1;            
	            all[j].enable();            
	        };
	        
	        // Disable subsequent steps
	        i = j + 1;
	        for (i; i < all.length; i += 1) {
	            all[i].disable();
	        }
	    };
	    
	    that.addStep = function(step) {
	    	step.steps = that;
	    	all.push(step);
	    }
	    
	    that.addSteps = function(stepsArray) {
	    	var i = 0;
	    	for (i; i < stepsArray.length; i += 1) {
	            that.addStep(stepsArray[i]);
	        }
	    }
	    
	    if(typeof stepsArray === 'object') {
	    	that.addSteps(stepsArray);
	    }
	    	    
	    return that;
	}
};

// Step class
/************************************************************************/
app.chain.step = function(spec) {
    var that = {},
    enabled, 									
    rules = [], 																// Rules: Checked in sequence, if passes
    $elements = typeof spec.css === 'string' ? $(spec.css) : [],				// Elements related to the step, reference stored
    enablePreFn = spec.enablePreFn || false,
    enablePostFn = spec.enablePostFn || false,
    disablePreFn = spec.disablePreFn || false,
    disablePostFn = spec.disablePostFn || false,
    forceTest = spec.forceTest || false,										// Never use cached test results
    omnitureEvent = spec.omniture || false;

    that.addRule = function(ruleSpec) {
        ruleSpec.step = that;
        rules.push(app.chain.rule(ruleSpec));
        return that;
    };

    that.testAllRules = function(force) {
        var i;
        if (rules.length < 1) {
            return true;
        }
        
        for (i = 0; i < rules.length; i += 1) {
        
        	if(force || forceTest) {
        		rules[i].test();
        	}
        
            if (!rules[i].rulePassed()) {
                return false;
            }
        }
        return true;
    };

    that.testSingleRule = function(i) {
    	return rules[i] && rules[i].test();
    };
    
    that.disable = function() {    	
    	if(enabled || typeof enabled === 'undefined') {
	    	if(typeof disablePreFn === "function") {
	    		disablePreFn();    	
	    	}
	        $elements.filter(':input').each(function() {
	            this.disabled = true;
	        }).addClass('disabledInput').end().hide();
	        enabled = false;
	    	if(typeof disablePostFn == "function") {
				disablePostFn();	    	
	    	} 
    	}    	
    }
    
    that.enable = function() {    	
    	if(!enabled || typeof enabled === 'undefined') {
    		if(typeof omnitureEvent === "object") {
    			omnitureEvent.log();
    		}
	    	if(typeof enablePreFn === "function") {
	    		enablePreFn();    	
	    	}		    	
	    	$elements.filter(':input').each(function() {
	            this.disabled = false;
	        }).removeClass('disabledInput').end().show();
	        enabled = true;		    	
	    	if(typeof enablePostFn == "function") {
				enablePostFn();	    	
	    	} 
    	}    	
    }
        
    return that;
}

// Rule class - element, rule, listener, name and message
// On test, checks rule and tests step
/************************************************************************/
app.chain.rule = function(spec) {
    var that = {},
    passed,
    step = spec.step || false,
    fn = spec.rule,
    el = spec.el,
    listenerSpec = spec.listenerSpec || { events : spec.events } || false;
    
    if(typeof listenerSpec === 'object') {
    	if (typeof listenerSpec.el === 'undefined') {
    		listenerSpec.el = spec.el;
    	}
    	app.chain.listener(listenerSpec, that)
    }

    that.rulePassed = function() {
        return typeof passed === 'undefined' ? that.test() : passed;
    };

    that.test = function() {
        return passed = fn($(el));
    };
    
    that.getStep = function() {
    	return step;
    }
    	
    return that;
}

// Listener class - element, fn
// On change executes rule.test and specified function then chains step tests
/************************************************************************/
app.chain.listener = function(spec, rule) {
    var fn = spec.fn || false,			// Run post-test with test result passed in
    el = spec.el || false,
    events = spec.events || false,
    rule = rule || false;
    
    $(el).live(events, function(evt) {        
    	if(spec.preventDefault) {
    		evt.preventDefault();
    	}        
        
        if (typeof fn === "function") {
            fn(rule ? rule.test() : true, $(el), evt);
        } else if (typeof rule.test === "function") {
            rule.test();
        }

        // !! Enable/disable steps as required
        if(typeof rule !== "undefined") {
            rule.getStep().steps.continueUntil();
        }
    });
}




// Forms
app.configure = function(options) {
	var options = options || {}, 
	hide = typeof options.hide === 'boolean' ? options.hide : true,
	optionals = options.optionals || false,
	dates = options.dates || false,
	deletes = options.deletes || false,
	keepAlive = options.keepAlive || false;
	
	if(hide) {
		app.hide();
	}
	
	if(optionals) {
		app.forms.optionals();
	}
	
	if(dates) {
		app.forms.dates();
	}
	
	if(deletes) {
		app.forms.deletes();
	}
	
	if(keepAlive) {
		app.forms.keepAlive();
	}
}

app.hide = function() {
	$('.hide').hide().removeClass('hide');
}

app.forms = {
	optionals : function() {	
		$('input.optional').each(function() {
			if($(this).val().length > 0) {
				$(this).prev('label').find('span.placeholder').hide();
			}
		}).focus(function() {
	    	$(this).prev('label').find('span.placeholder').hide();
	    }).blur(function() {
	  		if($(this).val().length === 0) {
	    		$(this).prev('label').find('span.placeholder').css('display', 'inline');
	    	}
	    });
	},
	dates : function() {	
		$('div.date input').each(function() {
			if($(this).val().length > 0) {
				$(this).prev('label').hide();
			}
		}).focus(function() {
	    	$(this).prev('label').hide();
	    }).blur(function() {
	  		if($(this).val().length === 0) {
	    		$(this).prev('label').css('display', 'inline');
	    	}
	    });
	},
	deletes : function() {
		$('a.delete').click(function(evt){
			return confirm("Are you sure you want to delete this?");
		});
	},
	keepAlive : function() {
		
		// Set timeout to Session length minus 5 mins, if no default, set to 25 mins
		var timeToListenFor = 5 * 60 * 1000,
			triggerListenersDelay = app.DEFAULTS && app.DEFAULTS.sessionExpires ? app.DEFAULTS.sessionExpires - timeToListenFor : 25 * 60 * 1000;
		
		app.timeout = setTimeout("app.keepAlive()", triggerListenersDelay);
		
		// Check for user action, otherwise let session expire
		app.keepAlive = function() {
			app.sessionExpires = setTimeout("app.sessionExpiring()", timeToListenFor + 1);
			$('body').bind('click keyup', function() {
				// make call to stop session expiry if page has action
				$.ajax({
	                type: 'GET',
	                url: app.DEFAULTS.keepAliveUrl || '/application.session.keepalive.aspx',
	                dataType: 'json',
	                success: function(result) {
	                	// on success, kill timeout
	                	// if error - leave timeout and warning will still show.
						app.timeout = setTimeout("app.keepAlive()", triggerListenersDelay);
						clearTimeout(app.sessionExpires);
	                }
	            });
				$('body').unbind();
			});
		};
		
		// Remove bind after session expires
		app.sessionExpiring = function() {
			$('body').unbind();
			$('h2').after('<p class="errorFlash"><strong>Warning</strong>: Your session has expired. This page has been left for longer than '+ ((triggerListenersDelay / 60 / 1000) + 5) +' minutes, for security reasons anything entered on this page will not be saved.</p>');
		}
	}
}

app.analytics = {
	event: function(spec) {
	    var that = {},
	    	name = spec.name,
	    	s,
	    	logged = false;
	    	
		that.log = function() {
			//console.log('logging... ' + name + ' - ' + spec.event);		
			if(typeof s_gi === "function" && !logged) {
	    		s = s_gi('tslnewdev');
	    		s.events = spec.event;
	    		s.linkTrackEvents = spec.event;
	    		s.linkTrackVars = spec.linkTrackVars || "events";
	    		s.tl(this,'o',name);		    		
	    		logged = true;
			}
		}
    	   	
		return that;    
	}
} 

app.cookie = {
 	create: function(name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	},
	read: function(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	},
	erase: function(name) {
		app.cookie.create(name,"",-1);
	}
}

$(function(){
	$('body').addClass('js');
	$('.hide').hide().removeClass('hide');
});
