/**
 * Initialise global functions and variables. This happens before all other 
 * libraries and script in the source order.
*/



/*******************************************************************************
* Namespace			                                                          **
*******************************************************************************/

if(window.openc == undefined) {
	openc = new Object();
}


/*******************************************************************************
* RIA, edit and  and desktop detection                                        **
*******************************************************************************/

openc.IS_RIA_CLIENT = jq.browser.msie || jq.browser.mozilla || jq.browser.safari || jq.browser.opera;
openc.IS_DESKTOP = screen.width > 480;
openc.IS_EDIT_PAGE = window.openc_edit_page ? true : false;



/*******************************************************************************
* Clean whitespace															  **
*******************************************************************************/

/**
 * Clean away any text nodes that are only whitespace. Often needed to clean
 * Kupu text
*/
openc.removeWhitespace = function(node) {
	jQuery.each(node.childNodes, function(index, node) {
	
		// If this is a text node, and contains only contiguous whitespace
		if(node && node.nodeType == 3 && node.nodeValue.match(/^\s*$/)) {
			// Remove it
			node.parentNode.removeChild(node);
		}
	});
}

/*******************************************************************************
* Contstants		                                                          **
*******************************************************************************/

// todo - strengthen this regex.
/*
^http:\/\/		Protocol
[^\/]+			Domain
([^\?@\+]*)		Capture path, anything except '?', '@' or '+
*/

openc.SITE_ADDRESS = document.location.href.replace(/(^http:\/\/[^\/]+\/).*$/, '$1');

openc.PATH_TO_PAGE = document.location.href.replace(/^http:\/\/[^\/]+([^\?@\+]*).*$/, '$1');
// If the path has any contiguous \/\ at the end, after a non slah character
if(openc.PATH_TO_PAGE.match(/[^\/]\/+$/)) {
	// Remove them
	openc.PATH_TO_PAGE = openc.PATH_TO_PAGE.replace(/^(.+[^\/])\/+$/, '$1');
}
openc.PAGE_NAME = openc.PATH_TO_PAGE.replace(/^.*\/([^\/]*)$/, '$1');

// Depth is determined by path
openc.PAGE_DEPTH = openc.PATH_TO_PAGE == "/" ? 0 : openc.PATH_TO_PAGE.match(/\//g).length;

// Log constants

openc.logConstants = function() {

	return;

	for(var prop in openc) {
		if(prop.match(/^[A-Z_]+$/)) {
			openc.log(prop + ' : ' + openc[prop]);
		}
	}
	
}

jq(function() {
	// Allow time for constancts to be registered by opther scripts
	setTimeout(openc.logConstants, 100);
});



/*******************************************************************************
* Utility			                                                          **
*******************************************************************************/


// Prevent flickering on image hover in MSIE

if(navigator.appVersion.indexOf('MSIE') > -1){
	try {
		document.execCommand("BackgroundImageCache", false, true);
	} catch(err) {}
}



/*******************************************************************************
* Event mediator	                                                          **
*******************************************************************************/

openc.EventMediator = function() {

	// Store references to registrations
	this.registry = new Object;
}

/**
 * Add listener
*/ 
openc.EventMediator.prototype.addEventListener = function(eventType, handler) {
	
	// Create an array if none exists for this event
	if(this.registry[eventType] == undefined) {
		this.registry[eventType] = new Array();
	}
	var eventRegistry = this.registry[eventType];
	
	// Check that handler does not already exist
	for(var i = 0 ; i < eventRegistry.length ; i++) {
		if(eventRegistry[i] == handler) {
			// openc.log('Passed handler already listening for ' + eventType + '!');
			return false;
		}
	}
	// Add handler as listener for event
	eventRegistry.push(handler);

}

/**
 * Dispatch event
*/
openc.EventMediator.prototype.dispatchEvent = function(eventType, eventObj) {

	var eventRegistry = this.registry[eventType];
	
	if(eventRegistry != undefined && eventRegistry.length > 0) {
		
		// For each listener
		for(var i = 0 ; i < eventRegistry.length ; i++) {
			
			// Call the listener and pass the event object
			eventRegistry[i].call(null, eventObj);
		}
	}
}

/**
 * Instantiate
*/
openc.eventMediator = new openc.EventMediator();





/*******************************************************************************
* Debug console		                                                          **
*******************************************************************************/

openc.log = function(str, clear) {
	// Create console if missing
	if(jq("div#opencLog").length == 0) {
		jq("body").prepend(
			jq('<div id="opencLog" style="position:absolute;top:10px;left:10px;width:600px;min-heigh400px;max-height:800px;overflow:auto;border:5px solid black;z-index:1000;background-color:black;color:green;font-family:monospace;font-size:13px;"></div>')
		)
		jq('div#opencLog').css('opacity',0.8);
	}
	var log = jq("div#opencLog");
	if(clear) {
		log.empty();
	}
	log.prepend('<p style="margin:5px;">' + str + '</p>');
	
	return str;
}





/*******************************************************************************
* Class inheritance 	                                                      **
*******************************************************************************/

Function.prototype.extend = function(superclass) {
    var c = function() {};
    c.prototype = superclass.prototype;
    this.prototype = new c();
}




/*******************************************************************************
* Object registration 	                                                      **
*******************************************************************************/

/**
 * TODO - rename 'Registry object' -- it's confuding. Perhaps 'Media collection'?
 *
 * Registry objects are **instances of classes** like openc.BannerImage and 
 * openc.BannerFlash which are bound to **one** DOM id and which implement an append 
 * method which accepts reistration via openc.registerObject. This means that a registry object 
 * may have several items, which register asynchronously. When the first item of RO is added, the
 * RO is created.
*/
openc.registryObjectsByDomId = new Object();

/**
 * Called directly from script within the HTML. Looks for 'type' and 'targetId'
 * properties with which to find (or create if necessary) the appropriate
 * registry object (openc.BannerFlash for example), and to call its append 
 * method, passing the object along.
*/

openc.registerObject = function(obj) {

	//TODO
	return

	// Find the target
	var targetId = obj.targetId;
	var target = jq("#" + targetId);
	
	// If there is no target
	if(target.length == 0) {
		// Do nothing
		return;
	}
	
	// If there is no registry for objects of this type, create one
	var registry = openc.registryObjectsByDomId;
	if(registry[obj.parentClass] == undefined) {
		registry[obj.parentClass] = new Array();
	}
	var typeRegistry = registry[obj.parentClass];
	
	// If a class instance does not exist to contain this object
	if(typeRegistry[targetId] == undefined) {
		// Create the instance
		typeRegistry[targetId] = new openc[obj.parentClass](target);
		// openc.log('Created registry for ' + obj.parentClass);
	}
	
	// Add the object to the class
	typeRegistry[targetId].append(obj);
}


/*******************************************************************************
* Consistent propert measurement                                              **
*******************************************************************************/

/**
 * Recursive function returns true when [element]'s [property] is the same 
 * [consistentMeasurementsRequired] number of times. It's measured at intervals of [interval] ms. 
 */
 
openc.callWhenPropertyConsistent = function(callImmediately, callback, element, property, consistentMeasurementsRequired, interval, log, lastMeasurement, consistentMeasurementsCount, i) {

	//openc.log("openc.callWhenPropertyConsistent called, element=" + element + ", property=" + property);
	
	// It's possible the elemtn to measure doesn't exist, if so do nothing
	if(element == undefined) {
		return false;
	}

	if(!i) {
		i == 0;
	}
	if(callImmediately) {
		callback();
		return true;
	}

	lastMeasurement = lastMeasurement ? lastMeasurement : 0;
	consistentMeasurementsCount = consistentMeasurementsCount ? consistentMeasurementsCount : 0;

	var thisMeasurement = element[property];
	// Prevent inifinite loops
	if(thisMeasurement == undefined) {
		openc.log("openc.callWhenPropertyConsistent ERROR - cannot mesure '" + property + "'");
		return false;
	}
	consistentMeasurementsCount = (thisMeasurement == lastMeasurement) ? consistentMeasurementsCount + 1 : 0;
	
	if(log) {
		openc.log("<br/><b>" + i + ". consistentBodySize<br/>thisMeasurement = " + thisMeasurement + "<br/>lastMeasurement = " + lastMeasurement + "<br/>consistentMeasurementsCount = " + consistentMeasurementsCount);
	}
	
	if(consistentMeasurementsCount == consistentMeasurementsRequired) {
		callback();
	}
	else {
		var closure = function() {
			openc.callWhenPropertyConsistent(false, callback, element, property, consistentMeasurementsRequired, interval, log, thisMeasurement, consistentMeasurementsCount, consistentMeasurementsCount, i++);
		}
		setTimeout(closure, interval);
	}
}




