
// --------------------------------------------------------
// 
// --------------------------------------------------------
function updateCompanyData (companyId)
{
	$("company-data-loading").style.display = "block";

	Transport.load({
		contentType: "text/plain",
		url: "company_data/" + companyId + ".html",
		onload: function (data)
		{
			$("company-data-loading").style.display = "none";
			$("company-data").innerHTML = data.contentPackage.result;
		},
		debug: true
	});
}

// --------------------------------------------------------
// 
// --------------------------------------------------------
function handleCompanySelection (e)
{
	// clear the old content
	$("company-data").innerHTML = "";
	
	// send the request for the new company
	var menuEl = $("media-company-list");
	updateCompanyData(menuEl.options[menuEl.selectedIndex].value);
};

// --------------------------------------------------------
// toggle the holdings / timeline data
// --------------------------------------------------------
function selectCompanyView (view)
{
	$("nav-who-owns-what").className = view;

	$("media-company-timeline").style.display = view == "timeline" ? "block" : "none";
	$("media-company-holdings").style.display = view == "holdings" ? "block" : "none";
};


// ------------------------------------------------------------
// Events
// ------------------------------------------------------------
var Events = {

	// needed to properly assign click events for safari
	isSafari: (/Safari|Konqueror|KHTML/gi).test(navigator.userAgent),
	
	ATTACH_TYPE_IMMEDIATE: 1,
	ATTACH_TYPE_WHEN_AVAILABLE: 2,
	ATTACH_TYPE_WHEN_DOM_AVAILABLE: 3,
	
	domLoadEvents: [],
	unloadEvents: [],
	attachedEvents: [],
	
	_hasUnloadWatcher: false,
	_domLoaded: false
	
};

Events._init = function ()
{
	this._initMonitorDOMLoad();
};

Events.addEvent = function ()
{
	var element;
	var eventType;
	var attachType = Events.ATTACH_TYPE_IMMEDIATE;
	var handler;
	var dataPackage;
	var trace = false;
	var context = null;
	var label = "";
	
	element = arguments[0].element;
	eventType = arguments[0].type;
	handler = arguments[0].handler;
	
	// if (typeof element == "undefined" || typeof eventType == "undefined" || typeof handler == "undefined")
	if (typeof eventType == "undefined" || typeof handler == "undefined" || (eventType.toLowerCase() != "domload" && typeof element == "undefined"))
	{
		return false;
	};
	
	eventType = eventType.toLowerCase();
	dataPackage = typeof arguments[0].data != "undefined" ? arguments[0].data : {};
	trace = (arguments[0].trace == true);
	label = typeof arguments[0].label != "undefined" ? arguments[0].label : "";
	
	if (typeof arguments[0].attachType != "undefined") attachType = arguments[0].attachType; 
	if (typeof arguments[0].context != "undefined") context = arguments[0].context;
	
	var status = false;
	
	if (eventType == "domload")
	{
		var domLoadEvent = {
			element: element, 
			eventType: eventType, 
			handler: handler, 
			context: context, 
			dataPackage: dataPackage, 
			trace: trace, 
			label: label
		};
		
		if (this._domLoaded)
		{
			this._executeDOMLoadEvent(domLoadEvent);
		}
		else
		{
			this.domLoadEvents.push(domLoadEvent);
		};
				
		/*
		if (this.domLoadEvents.length == 1)
		{
			this._initMonitorDOMLoad();
		};
		*/
	}
	else if (eventType == "unload")
	{
		this.unloadEvents.push({
			element: element, 
			eventType: eventType, 
			handler: handler, 
			context: context, 
			dataPackage: dataPackage, 
			trace: trace, 
			label: label
		});
		
		this._initUnloadHandler();
	}
	else
	{
		if (attachType == this.ATTACH_TYPE_IMMEDIATE)
		{
			var trigger = this._createTrigger(element, handler, context, dataPackage, trace, label);
			status = this._attachEvent(element, eventType, trigger);
		} 
		else if (attachType == this.ATTACH_TYPE_WHEN_AVAILABLE)
		{
			this._monitorDOMElementLoad(element, eventType, handler, context, dataPackage, trace, label, 0);
			status = true;
		}
		else if (attachType == this.ATTACH_TYPE_WHEN_DOM_AVAILABLE)
		{
		
		}
		else
		{
			status = false;
		};
	};
	
	return status;
};

Events.cancelEvent = function (e) 
{
	if (e) 
	{
		if (e.preventDefault) 
		{
			e.preventDefault();
		};
		
		if (e.stopPropagation)
		{
			e.stopPropagation()
		};
		
		e.cancelBubble = true;
		e.returnValue = false;
	};
	
	return false;
};

Events.add = Events.addEvent;
Events.cancel = Events.cancelEvent;

/* create a closure to allow us to customize the event handler call */
Events._createTrigger = function (element, handler, context, dataPackage, trace, label)
{
	if (context != null)
	{
		handler = hitch(context, handler);
	}
	else if (element != null)
	{
		handler = hitch(element, handler);
	};
	
	return function () 
	{
		var e = arguments.length ? arguments[0] : window.event;
		var el = e != null ? Events._getSrcElement(e) : null;
		
		if (trace) 
		{
			dbg("Event Triggered");
			dbg("Event Info", e.type);
			dbg("Object Info", el.tagName + (el.id ? ": " + el.id : ""));
			dbg("Handler Label", label);
		};
		
		handler(e, el, dataPackage);
	};
};

Events._attachEvent = function (element, eventType, trigger)
{
	var status = false;
	
	this._initUnloadHandler();
	
	if (this._useLegacyEvent(element, eventType))
	{
		status = this._attachLegacyEvent(element, eventType, trigger);
	}
	else if (element.addEventListener) 
	{
		element.addEventListener(eventType, trigger, false /* isCapture */ );
		status = true;
	}
	else if (element.attachEvent) 
	// Internet Exploder
	{
		// return element.attachEvent("on" + eventType, trigger);
		status = this._attachLegacyEvent(element, eventType, trigger);
	}
	else 
	{
		status = false;
	};
	
	this.attachedEvents.push({
		element: element,
		eventType: eventType,
		handler: trigger,
		useCapture: false
	});

	return status;			
};

Events._useLegacyEvent = function (element, eventType) 
{
	if (!element.addEventListener && !element.attachEvent) 
	{
		return true;
	} 
	else if (this.isSafari)
	// safari won't let us cancel click events, so 
	// we will assign them with the onclick property
	{
		if (eventType == "click" || eventType == "dblclick") 
		{
			return true;
		};
	};

	return false;
};

Events._attachLegacyEvent = function (element, eventType, trigger)
{
	eventType = "on" + eventType;
		
	if (typeof element[eventType] == "function")
	{
		var prevHandler = element[eventType];
		
		element[eventType] = function ( /* e */ )
		{
			prevHandler();
			trigger();
		};
	}
	else
	{
		element[eventType] = trigger;
	};
	
	return true;
};

Events._monitorDOMElementLoad = function (element, eventType, handler, context, dataPackage, trace, label, count)
{
	if (typeof document.getElementsByTagName != "undefined" && (document.getElementsByTagName("body")[0] != null || document.body != null) && $(element))
	{
		// get the element node
		element = $(element);
	
		// create the handler closure
		var trigger = this._createTrigger(element, handler, context, dataPackage, trace, label);
		
		if (eventType == "load")
		{
			trigger();
		}
		else
		// attach it
		{
			// return this._attachEvent(element, eventType, trigger);
			
			Events.add({
				type: "domload",
				handler: function ()
				{
					Events._attachEvent(element, eventType, trigger);
				}
			});
					
		};
	}
	else
	{
		// retry for up to a minute
		if (++count < 600)
		{
			setTimeout(function ()
			{
				Events._monitorDOMElementLoad(element, eventType, handler, context, dataPackage, trace, label, count);
			}, 100);
		};
	};
};

Events._initMonitorDOMLoad = function ()
{
	if (document.addEventListener)
	{
		document.addEventListener("DOMContentLoaded", function () 
		{
			Events._handleDOMLoad();
		}, null);
	};
	
	if (typeof document.readyState != "undefined")
	{
		if (document.all)
		{
			document.write("<script defer id=\"_domLoadMonitor\" src=\"javascript:void(0)\"><" + "/script>");
		};
		
		this._monitorDOMLoad();
	};

	// todo: need an onload handler that checks to see if these events have fired
	
};

Events._monitorDOMLoad = function ()
{
	var monitorEl = $("_domLoadMonitor") || document;
	
	// loading | interactive | loaded | complete
	if (monitorEl.readyState == "complete")
	{
		this._handleDOMLoad();
	}
	else
	{
		setTimeout(function ()
		{
			Events._monitorDOMLoad();
		}, 10);	
	};
};

Events._handleDOMLoad = function ()
{
	var domLoadEvent;
	
	this._domLoaded = true;
	
	while (domLoadEvent = this.domLoadEvents.pop())
	{
		// this._createTrigger(domLoadEvent.element, domLoadEvent.handler, domLoadEvent.context, domLoadEvent.dataPackage, domLoadEvent.trace, domLoadEvent.label)();
		this._executeDOMLoadEvent(domLoadEvent);
	};
};

Events._executeDOMLoadEvent = function (domLoadEvent)
{
	this._createTrigger(domLoadEvent.element, domLoadEvent.handler, domLoadEvent.context, domLoadEvent.dataPackage, domLoadEvent.trace, domLoadEvent.label)();
};

Events._initUnloadHandler = function ()
{
	if (!this._hasUnloadWatcher)
	{
		this._hasUnloadWatcher = true;
		this._attachEvent(window, "unload", hitch(this, this._handleUnload));
	};
};

Events._handleUnload = function ()
{
	var unloadEvent;
	
	while (unloadEvent = this.unloadEvents.pop())
	{
		this._createTrigger(
			unloadEvent.element, 
			unloadEvent.handler, 
			unloadEvent.context, 
			unloadEvent.dataPackage, 
			unloadEvent.trace, 
			unloadEvent.label
		)();
	};
	
	for (var i = 0; i < this.attachedEvents.length; i++)
	{
		if (this.attachedEvents[i].element.removeEventListener)
		{
			this.attachedEvents[i].element.removeEventListener(
				this.attachedEvents[i].eventType, 
				this.attachedEvents[i].handler, 
				this.attachedEvents[i].useCapture
			);
		}
		else
		{
			this.attachedEvents[i].element["on" + this.attachedEvents[i].eventType] = null;
		};
	};
};

Events._getSrcElement = function ()
{
	var el = arguments[0].srcElement || arguments[0].currentTarget || window;

	try
	{
		/* Safari triggers events on text nodes :: this is probably incorrect; handlers should be using 'this' instead */
		if (el.nodeType == 3)
		{
			el = el.parentNode;
		};
	}
	catch (e)
	{
		el = window;
	};
	
	return el;
};

/*
Events.disableTextSelect = function () 
{
	if (!document.onselectstart) 
	{
		document.onselectstart = function() 
		{
			cancelEvent();
			return false;
		};
	};
};

Events.enableTextSelect = function () 
{
	if (document.onselectstart) 
	{
		document.onselectstart = null;
	};
};
*/

Events._init();

// ------------------------------------------------------------------------------------------------------------
// 
// ------------------------------------------------------------------------------------------------------------
var Transport = { 

	connections: [],
	connectionsMax: 100,
	connectionsActive: 0,
	connectionsPending: [],
	debug: true,
	context: window,
	connectionId: 0

};

if (typeof dbg != "function")
{
	dbg = function (a, b) 
	{
		// console.log(a + ":" + b)
	};
};

Transport.load = function (contentPackage) 
{
	// data validation
	try 
	{
		contentPackage.method = contentPackage.method.toLowerCase();
	
		if (contentPackage.method != "get" && contentPackage.method != "post") 
		{
			contentPackage.method = "get";
		};
	} 
	catch (e) 
	{
		contentPackage.method = "get";
	};

	if (contentPackage.postdata && !contentPackage.data) 
	{
		contentPackage.data = contentPackage.postdata;
	} 
	else if (!contentPackage.data) 
	{
		contentPackage.data = {};
	};
	
	contentPackage.loadTime = new Date();
	
	if (!contentPackage.delay)
	{
		contentPackage.delay = 0;
	};
	
	/*
	// enable cache flushing
	if (document.location.search.match(/\.\.nocache\.\.=on/i)) 
	{
		contentPackage.data["..nocache.."] = "on";
	};
	*/
		
	return new Connection(this, this.connectionId++, contentPackage);
};

// ------------------------------------------------------------------------------------------------------------
// loadXMLHTTP()
// ------------------------------------------------------------------------------------------------------------
Transport._loadXMLHTTP = function (connection) 
{
    var thisConnection = connection;
    var contentPackage = thisConnection.contentPackage;

	function stateMonitor () 
	{
		thisBuffer._monitorConnectionState(thisConnection);
	};

	this.connectionsActive++;

    /*
	if (!this.connections.length) 
	{
		if (!this.initConnection()) 
		{
			if (this.debug || contentPackage.debug) 
			{
				dbg("Transport initialization error", "unsupported", "red");
			};
			
			return;
		};
	};
    */

	var dataPackage = null;
	var thisBuffer = this;

	thisConnection.active = true;
	//contentPackage.connectionId = this.connectionId++; // necessary?

	if (typeof contentPackage.contentType == "string") 
	{
		contentPackage.data["..contenttype.."] = contentPackage.contentType;
	};

	// uniquely identify Transport requests
	contentPackage.data["..requester.."] = "Transport";
	
	contentPackage.data["..d.."] = new Date().getTime();
	// contentPackage.method = "get";

	if (contentPackage.method == "post") 
	{
		dataPackage = "";

		for (var i in contentPackage.data) 
		{
			dataPackage += (dataPackage.length ? "&" : "") + this.encode(i) + "=" + this.encode(contentPackage.data[i]);
		};

		if (this.debug || contentPackage.debug) 
		{
			dbg("Transport post data", dataPackage);
		};

	} else 
	{
		for (var i in contentPackage.data) 
		{
			contentPackage.url += (contentPackage.url.indexOf("?") == -1 ? "?" : "&") + this.encode(i) + "=" + this.encode(contentPackage.data[i]);
		};
	};

	if (this.debug || contentPackage.debug) 
	{
		// dbg("Transport loading [" + contentPackage.connectionId + "]", contentPackage.url + " [" + contentPackage.method + "]");
		dbg("Transport loading [" + thisConnection.connectionId + "]", contentPackage.url + " [" + contentPackage.method + "]");
	};

	if (this.debug || contentPackage.debug) 
	{
		var debugUrl = contentPackage.url;

		if (dataPackage) 
		{
			debugUrl += (debugUrl.indexOf("?") == -1 ? "?" : "&") + dataPackage;
		};

		debugUrl = debugUrl.replace(/\&?\.\.[^\=\&]*\.\.\=[^\&]*/g, "");
		dbg("Transport URL", "<a href=\"" + debugUrl + "\" target=\"_blank\">" + debugUrl + "</a>");
	};
	
	try 
	{
		// netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    	thisConnection.c.open(contentPackage.method.toUpperCase(), contentPackage.url, true);
		thisConnection.c.onreadystatechange = stateMonitor;
	} 
	catch (e) 
	{
		// alert(e);
	};

	if (contentPackage.method == "post") 
	{
		thisConnection.c.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		// thisConnection.c.setRequestHeader("Cache-Control", "public");
		// thisConnection.c.setRequestHeader("Pragma", "public");
		// thisConnection.c.setRequestHeader("Keep-Alive", 0);
		// thisConnection.c.setRequestHeader("Connection", "bleh");
	};

	// thisConnection.contentPackage = contentPackage;
	// dbg(thisConnection.c.send(), "trying connectionId");
	
	// dbg(contentPackage.url + ":" + dataPackage + ":" + contentPackage.method);
	
	thisConnection.c.send(dataPackage);

	//return thisConnection;
};

// ------------------------------------------------------------------------------------------------------------
// monitorConnectionState()
// ------------------------------------------------------------------------------------------------------------
Transport._monitorConnectionState = function (connection) 
{
	try 
	{		
		if (connection.c.readyState == 4) 
		{
			/*
			try
			{
				connection.c.onreadystatechange = null;
				connection.c.abort();
				// delete connection.c;
			}
			catch (eee)
			{
				alert("$" + eee.message);
			};
			*/
						
			if (typeof connection.c.status != "undefined" && connection.c.status != 200 && connection.c.status != 0)
			{
				if (this.debug || connection.contentPackage.debug) 
				{	
					dbg("Transport load error", connection.c.status, "red");
					dbg("Transport result [" + connection.connectionId + "]", connection.c.responseText.length > 200 ? connection.c.responseText.substring(0, 200) + "..." : connection.c.responseText);
				};
								
				try 
				{
					var result = connection.c.responseText;
				} 
				catch (e) 
				{
					var result = null;
				};
								
				connection.contentPackage.result = result;

				if (typeof connection.contentPackage.onerror == "function") 
				{
					connection.contentPackage.onerror.apply(connection.context, [connection]);
				};

				return;
			};

			var responseType = connection.contentPackage.contentType || connection.c.getResponseHeader("Content-Type");
			var result = null;
			
			if (responseType.indexOf("text/html") != -1 || responseType.indexOf("text/plain") != -1)
			{
				result = connection.c.responseText;
			} 
			else if (responseType == "text/xml") 
			{
				// result = connection.c.responseXML || connection.c.responseText;
				result = connection.c.responseText;
				// alert(result);
			} 
			else if (responseType == "text/javascript") 
			{
				try 
				{
					result = connection.c.responseText;

					if (!connection.contentPackage.preventEval) 
					{	
						connection.context.__evalBuffer = function () 
						{
							eval(result);
						};
	
						connection.context.__evalBuffer();
					};
				} 
				catch (e) 
				{
					if (this.debug || connection.contentPackage.debug) 
					{
						dbg("Transport javascript eval error", e.message, "red");
						// if (typeof dbgObject != "undefined"){ dbgObject(e); }
					};
				};
			};

			connection.contentPackage.result = result;

			if (this.debug || connection.contentPackage.debug) 
			{
				var dbgResult = result.replace(/\</g, "&lt;").replace(/\>/g, "&gt;");
				
				if (dbgResult.length > 200)
				{
					dbgResult = dbgResult.substring(0, 200) + "...";
				};
				
				dbg("Transport result [" + connection.connectionId + "]", dbgResult);
			};

			if (typeof connection.contentPackage.onload == "function") 
			{
				var now = new Date();
				var diff = (connection.contentPackage.loadTime.getTime() + connection.contentPackage.delay) - now.getTime();
				
				if (diff > 0)
				{
					setTimeout(function ()
					{
						connection.contentPackage.onload.apply(connection.context, [connection]);
					}, diff);
				}
				else
				{
					connection.contentPackage.onload.apply(connection.context, [connection]);
				};
			};

			connection.active = false;
			this.connectionsActive--;

			if (this.connectionsPending.length) 
			{
				this._loadXMLHTTP(this.connectionsPending.shift());
			};
		};

	} 
	catch (e) 
	{
		if (this.debug || connection.contentPackage.debug) 
		{
			dbg("state monitoring error", e.message, "red");
			// Transport.abortRequests();
			
			/*	
			if (typeof dbgObject != "undefined")
			{ 
				dbgObject(e); 
			};
			*/
		};
	};
};

// ------------------------------------------------------------------------------------------------------------
// isActive
// ------------------------------------------------------------------------------------------------------------
Transport.isActive = function() 
{
	for (var i = 0; i < this.connections.length; i++) 
	{
		if (this.connections[i].active) 
		{
			return true;
		};
	};

	return false;
}

// ------------------------------------------------------------------------------------------------------------
// abortRequests()
// ------------------------------------------------------------------------------------------------------------
Transport.abortRequests = function () 
{
	for (var i = 0; i < this.connections.length; i++) 
	{
		this.connections[i].abort();
	};
}

// ------------------------------------------------------------------------------------------------------------
// abortRequests()
// ------------------------------------------------------------------------------------------------------------
Transport.abortRequests = function () 
{
	for (var i = 0; i < this.connections.length; i++) 
	{
		this.connections[i].abort();
	};
}

// ------------------------------------------------------------------------------------------------------------
// encode()
// ------------------------------------------------------------------------------------------------------------
Transport.encode = function(str) 
{
	// return escape(str);
	// ref: http://xkr.us/articles/javascript/encode-compare/
	return encodeURIComponent(str);
}

// ------------------------------------------------------------------------------------------------------------
// Connection class
// ------------------------------------------------------------------------------------------------------------
function Connection (transport, id, contentPackage) 
{
	this.active = false;
	this.parent = transport;
	this.connectionId = id;
	this.contentPackage = contentPackage;
	this.context = contentPackage.context || this.parent.context;
	this._init();
};

Connection.prototype._init = function() 
{
    var c = false;

	try 
	{
		c = new ActiveXObject("Msxml2.XMLHTTP");
	} 
	catch (e) 
	{
		try 
		{
			c = new ActiveXObject("Microsoft.XMLHTTP");
		} 
		catch (f) 
		{
			c = false;
		};
	};

	if (!c && typeof XMLHttpRequest != "undefined") 
	{
		c = new XMLHttpRequest();
	};

	if (c) 
	{
		this.c = c;
	} 
	else 
	{
		dbg("Content Buffer initialization error.", "Not supported by this browser", "red");
	};

    if (this.parent.connectionsActive < this.parent.connectionsMax) 
    {
        this.parent.connections.push(this);
        this.parent._loadXMLHTTP(this);
    } 
    else 
    {
        dbg("queuing request");
        this.parent.connectionsPending.push(this);
    };
};

Connection.prototype.getResult = function() 
{
    return this.contentPackage.result;
};

Connection.prototype.status = function() 
{
	return (this.c.readyState == 4 && this.c.status == 200);
};

Connection.prototype.abort = function() 
{
	if (this.active) 
	{
		try 
		{
			this.c.onreadystatechange = null;
			this.c.abort();
		} 
		catch (e) 
		{
			dbg("connection abort failed", e, "red");
		};
	};
};

// --------------------------------------------------------------------------
// $()
// Shorthand.
// --------------------------------------------------------------------------
function $ (id) 
{
	return document.getElementById ? document.getElementById(id) : document.all[id];
};

// --------------------------------------------------------------------------
// hitch()
// Associate an object + method, and force the right this context.
// Usage: button.onclick = hitch(Davey, Davey.init);
// --------------------------------------------------------------------------
function hitch (obj, meth) 
{
	return function () 
	{
		return typeof meth == "function" ? meth.apply(obj, arguments) : obj[meth].apply(obj, arguments); 
	};
};

// --------------------------------------------------------
// 
// --------------------------------------------------------
Events.add({
	element: window,
	type: "load",
	handler: function ()
	{
		try
		{
			var args = document.location.search.replace(/\?/, "").split("&");
			
			for (var i = 0; i < args.length; i++)
			{
				var fields = args[i].split("=");
				
				if (fields[0] == "c")
				{
					updateCompanyData(fields[1]);
					break;
				};
			};
		}
		catch (e)
		{
		
		};
	}
});


// --------------------------------------------------------
// 
// --------------------------------------------------------
Events.add({
	element: "media-company-list",
	type: "change",
	attachType: Events.ATTACH_TYPE_WHEN_AVAILABLE,
	handler: handleCompanySelection
});
