/**
 * The output map presents an on-screen visual representation of
 * a data source as markers over a map implementation
 */
HYSMaps.OutputMap = function (factory, input, element) {
	
	this.factory = factory; // map factory
	this.input = input; // path to XML data
	
	this.dom = {
		
		base: element,
		header: document.createElement('h2'),
		controls: {
			top: document.createElement('ul'),
			base: document.createElement('ul')
		},
		types: {
			base: document.createElement('ul'),
			wrapper: document.createElement('div'),
			header: document.createElement('div')
		},
		overlay: {
			base: document.createElement('div'),
			wrapper: element.getElementsByTagName('div')[0],
			bg: document.createElement('div'),
			close: document.createElement('a'),
			content: document.createElement('div')
		}
	};
	
	this.dom.controls.base.className = 'controls';
	
	this.dom.base.insertBefore(this.dom.controls.base, this.dom.base.firstChild);
	
	this.dom.controls.top.className = 'controls date';
	this.dom.base.insertBefore(this.dom.controls.top, this.dom.controls.base);
	
	this.dom.types.base.className = 'types';
	this.dom.types.header.className = 'header';
	
	this.dom.types.wrapper.className = 'types';
	this.dom.types.wrapper.appendChild(this.dom.types.header);
	this.dom.types.wrapper.appendChild(this.dom.types.base);
	this.dom.base.appendChild(this.dom.types.wrapper);
	
	this.dom.header.className = 'header';
	this.dom.base.insertBefore(this.dom.header, this.dom.base.firstChild);
	
	this.dom.overlay.close.setAttribute('href', '#');
	this.dom.overlay.close.className = 'close';
	this.dom.overlay.close.innerHTML = 'Close';
	this.dom.overlay.content.className = 'content';
	this.dom.overlay.bg.className = 'bg';
	
	var clickEvent = new HYSMaps.CloseClick(this.dom.overlay.base);
	this.dom.overlay.close.onclick = clickEvent.action;
	
	this.dom.overlay.base.setAttribute('id', 'map-overlay');
	this.dom.overlay.base.appendChild(this.dom.overlay.close);
	this.dom.overlay.base.appendChild(this.dom.overlay.content);
	this.dom.overlay.base.appendChild(this.dom.overlay.bg);
	this.dom.overlay.wrapper.insertBefore(this.dom.overlay.base, this.dom.overlay.wrapper.firstChild);
};
/**
 * Start parsing XML input data
 */
HYSMaps.OutputMap.prototype.initialise = function () {
	
	var parser = new HYSMaps.InputParser;
	parser.parse(this.input, this);
};

/**
 * This function is called when data is received and parsed
 */
HYSMaps.OutputMap.prototype.onData = function (data) {
	
	this.series = data.series || {};
	var params = data.map || {};
	
	this.initMap(params);
};

/**
 * Initialise the map
 */
HYSMaps.OutputMap.prototype.initMap = function (params) {
	
	// select map implementation
	this.map = this.factory.createMap(params.provider, params.type, params.plotter);
	if (!this.map) return false;
	
	// set title
	this.dom.header.innerHTML = params.title;
	
	// initialise series specific functionality
	for (var i in this.series) {
		this.series[i].initMap(this);
	}
	
	// initialise points on map (don't do redraw yet)
	this.initPoints(false);

	// set the map centre
	if (params.override) {
		this.map.setCentre(new HYSMaps.GeoCoords(params.override.latitude, params.override.longitude), params.override.zoom);
	}
	else {
		this.map.setCentre();
	}
	this.map.redraw();
   	
   	// loaded OK
   	this.dom.base.className += ' loaded';
   	return true;
};

/**
 * Ask series to plot their points
 */
HYSMaps.OutputMap.prototype.initPoints = function (redraw) {
	
	this.map.clearMarkers();

	for (var i in this.series) {
		this.series[i].updatePoints(this); // add points to map
	}
	
	if (redraw !== false) this.map.redraw();
};

/**
 * Add controls for each series (checkboxes for toggling each series)
 */
HYSMaps.OutputMap.prototype.addControl = function (series, name, icon) {
	
	// series control
	var input = document.createElement('input');
	input.setAttribute('type', 'checkbox');
	input.setAttribute('checked', 'checked');
	input.setAttribute('defaultChecked', 'defaultChecked');
	input.onclick = this.toggleSeries.bind(this, series);
	
	var label = document.createElement('label');
	var text = document.createTextNode(name);
	label.appendChild(text);
	label.appendChild(input);
	label.style.backgroundImage = "url('" + icon.image + "')";

	var control = document.createElement('li');
	control.appendChild(label);
	
	this.dom.controls.base.appendChild(control);
};

/**
 * Add controls for toggling the types within each series
 */
HYSMaps.OutputMap.prototype.addType = function (series, type, icon) {
		
	// types control
	var span = document.createElement('span');
	var text = document.createTextNode(type);
	span.appendChild(text);

	var input = document.createElement('input');
	input.setAttribute('type', 'checkbox');
	input.onclick = this.toggleType.bind(this, series, type);

	var label = document.createElement('label');
	label.appendChild(span);
	label.appendChild(input);
	input.setAttribute('checked', 'checked');
	input.setAttribute('defaultChecked', 'defaultChecked');
	label.style.backgroundImage = "url('" + icon.image + "')";

	var control = document.createElement('li');
	control.appendChild(label);

	this.dom.types.base.appendChild(control);
	this.dom.types.header.innerHTML = "Users selected from the following options: ";
};

/*
 * Add a date-filter control
 */
 
HYSMaps.OutputMap.prototype.addDateFilter = function (series, limit, byline, headline, active) 
{
	var div = document.createElement('div');
	
	var oHeadline = document.createElement('span');
	oHeadline.innerHTML = headline || 'Most recent ' + limit + ' comments';
	div.appendChild(oHeadline);
	
	if (byline) {
		var oByline = document.createElement('span');
		oByline.innerHTML = "<br />(" + byline + ")";
		div.appendChild(oByline);
	}
	
	var input = document.createElement('input');
	input.setAttribute('type', 'checkbox');
	input.onclick = this.onDateFilter.bind(this, series, input, oHeadline, limit);
	
	var label = document.createElement('label');
	label.appendChild(input);
	label.appendChild(div);
	
	if (active) {
		oHeadline.className += " active";
		input.setAttribute('checked', 'checked');
		series.toggleFiltering(limit);
	}
	
	var control = document.createElement("li");
	control.appendChild(label);
	
	this.dom.controls.top.appendChild(control);
};

HYSMaps.OutputMap.prototype.addPoint = function (point, coords, icon, date, grouped) 
{
	var marker = this.map.addMarker(coords, icon, date, grouped);
	if (marker) {
		var clickEvent = point.makeClickEvent(this.dom.overlay.base, this.dom.overlay.content);
		this.map.bind(marker, 'mouseup', clickEvent, clickEvent.action);
	}
};

HYSMaps.OutputMap.prototype.toggleSeries = function (series) {
	
	series.toggle();
	this.initPoints();
};

HYSMaps.OutputMap.prototype.toggleType = function (series, type) {
	
	series.toggleType(type);
	this.initPoints();
};

/*
 * Respond to date-filter changes
 */

HYSMaps.OutputMap.prototype.onDateFilter = function (series, object, headline, limit) 
{
	var headlines = this.dom.controls.top.getElementsByTagName('span');
	for (var i = 0; i < headlines.length; ++i) headlines[i].className = '';
	
	var inputs = this.dom.controls.top.getElementsByTagName('input');
	for (var i = 0; i < inputs.length; ++i) inputs[i].checked = '';
	
	headline.className = "active";
	object.checked="checked";
	series.toggleFiltering(limit);
	this.initPoints();
}


HYSMaps.OutputMap.prototype.unload = function () {
	
	var inputs = this.dom.controls.base.getElementsByTagName('input');
	for (var i = 0; i < inputs.length; ++i) {
		inputs[i].onclick(Function.prototype.unbind);
	}
	var inputs = this.dom.types.base.getElementsByTagName('input');
	for (var i = 0; i < inputs.length; ++i) {
		inputs[i].onclick(Function.prototype.unbind);
	}
	this.dom.overlay.close.onclick = null;
	
	if (this.map) this.map.unload();
};