function loadColumnBrowser(surface)
{
	new ColumnBrowser(surface);	
	document.fire('items:listFromHash');
}

/* ----- COLUMN BROWSER OBJECT ----- */

var ColumnBrowser = Class.create();

ColumnBrowser.prototype = {
	initial_columns: null,		// This stores the order of the columns as defined by the config
	columns: null,						// This stores the order of the columns as they appear on the screen
	columns_lookup: null,			// This is a reverse lookup to access the columns if you only know the 'id' (JS Object not DOM Element)
	surface: null,						// The DOM Element for the Columns (a UL)
	container: null,					// The DOM Element that encloses the Column (surface) Element
	container_surface: null,	// The DOM Element all elements are held in - passed in to the constructor
	
	initialize: function(surface)
	{
		this.container_surface = $(surface);	// Save the surface of where to draw everything
		
		//var header = $(document.createElement('div'));
		//header.innerHTML = "Number of Results: <span id=\"ItemCount\"></span> (<a href=\"#\" onclick=\"document.fire('column:showitems')\">Show tracks</a>)";
		
		
		this.container = $(document.createElement('div'));
		this.container.setAttribute('id', 'CBContainer');
		this.surface = $(document.createElement('ul'));	
		this.surface.setAttribute('id', 'CB');
		this.container.appendChild(this.surface);	
		
		var itemslist = $(document.createElement('div'));
		itemslist.setAttribute('id', 'ItemsList');
		
		//this.container_surface.appendChild(header);
		this.container_surface.appendChild(this.container);
		//this.container_surface.appendChild(itemslist);
		this.container_surface.insert({after: itemslist});
		
		// Empty the element
		if ( this.surface.hasChildNodes() )
		{
	    while ( this.surface.childNodes.length >= 1 )
        this.surface.removeChild( this.surface.firstChild );       
		}

		this.resetColumns();
		
		var cc = new Element('div', {'id': 'ColumnClose'} ).update('<span>close columns</span>')
		this.container_surface.insert( cc );
		cc.down('span').observe('click', (function( event ) { this.close() }).bindAsEventListener(this) );
		
		document.observe('column:selectitem',	this.selectItem.bindAsEventListener(this));
		document.observe('column:showitems',	this.showItems.bindAsEventListener(this));
		document.observe('column:open',			this.open.bindAsEventListener(this));
		document.observe('items:list',			this.list.bindAsEventListener(this));
		document.observe('items:listFromHash',	this.listFromHash.bindAsEventListener(this));
	},
	
	list: function(e)
	{
		var params = e.memo;

		$('main-body').update( '<div id="main-body-loading"><img src="/staticfiles/img/global/ajax-loading.gif" /></div>' );
		
		// Make the request
		new Ajax.Updater('main-body', '/columns/showlist', {
			method: 'post',
			parameters: 'id='+params['id']+"&order="+params['order']+"&direction="+params['direction']+"&page="+params['page']+"&oc="+params["order_link_clicked"],
			evalScripts: true,
			onComplete: function() { document.fire('Search:Complete'); }
		});
	},
	
	listFromHash: function(e)
	{
		var hash = window.location.hash.substring(1);
		var params = hash.parseQuery();

		if(!params['id'])
			return;
		
		var paramString = 'id='+params['id'];
		
		if(params['order'])
			paramString += "&order="+params['order'];
			
		if(params['page'])
			paramString += "&page="+params['page'];	
			
		if(params['direction'])
			paramString += "&direction="+params['direction'];

		if(params['order_link_clicked'])
		{
			paramString += "&oc="+params['order_link_clicked'];					
		}

		$('main-body').update( '<div id="main-body-loading"><img src="/staticfiles/img/global/ajax-loading.gif" /></div>' );
		
		// Make the request
		new Ajax.Updater('main-body', '/columns/showlist', {
			  method: 'post',
			  parameters: paramString,
			  evalScripts: true,
			onComplete: function() { document.fire('Search:Complete'); }
		});
	},
	
	resize: function(e)
	{
		var width = 10;
		
		for(var i=0; i<this.columns.length; i++)
		{
			width += this.columns[i].getColumnWidth();
			
			// Calc height
			var height = this.columns[i].surface.getHeight() - this.columns[i].name_surface.getHeight();
			this.columns[i].list_container.setStyle({height: height+'px'});
		}
		
		// If the surface is hidden then we'll get the wrong result so assume the size is large
		if(this.container_surface.getStyle('display') == 'none')
			width = 700;
		
		this.surface.setStyle({width: width+'px'});	
		
		if(width > 770)
			this.container.setStyle({width: '820px'});
		else
			this.container.setStyle({width: 'auto'});
	},
	
	open: function(e)
	{
		$('main-body').fade({ duration: 0.3, to:0.1});
		$('KeywordSearch').hide();
		
		var first_col = e.memo;
				
		// Put the chosen column to the front of the list
		this.columns = new Array();
		
		var index = 1;
		if(this.initial_columns)
		{
			for(var i=0; i<this.initial_columns.length; i++)
			{
				if(this.initial_columns[i]['id'] == first_col)
					this.columns[0] = this.initial_columns[i];
				else
				{
					this.columns[index++] = this.initial_columns[i];	
				}
			}
		}
		
		//this.container_surface.setStyle({display: 'block'});
		$('ColumnBrowser').show();
		this.resetColumns();
	},
	
	close: function()
	{
		$('ColumnBrowser').hide();
		$('main-body').fade({ duration: 0.3, to:1});
	},
	
	showItems: function(e)
	{
		var found = false;
		
		var cols = '&';
		var vals = '&';
		
		// Loop through the columns and populate the ones that we need
		for(var i=0; i < this.columns.length; i++)
		{
			cols += 'cols[]='+this.columns[i]['id']+'&';
				
			if(this.columns_lookup[this.columns[i]['id']].selected)
				vals += 'vals[]='+this.columns_lookup[this.columns[i]['id']].getSelectedID()+'&';
			else
				vals += 'vals[]=&';
		}
		
		$('main-body').update( '<div id="main-body-loading"><img src="/staticfiles/img/global/ajax-loading.gif" /></div>' );
		
		// Make the request
		new Ajax.Updater('main-body', '/columns/items', {
			  method: 'post',
			  parameters: cols+vals,
			  evalScripts: true,
			onComplete: function() { document.fire('Search:Complete'); }
		});
		
		//$('ColumnBrowser').hide();
		this.close();
	},
	
	selectItem: function(e)
	{		
		var params = e.memo;
		var found = false;
		
		var cols = '&';
		var vals = '&';
		
		// Loop through the columns and populate the ones that we need
		for(var i=0; i < this.columns.length; i++)
		{
			cols += 'cols[]='+this.columns[i]['id']+'&';
				
			if(!found)
			{
				var collook = this.columns_lookup[this.columns[i]['id']];
				vals += 'vals[]='+collook.getSelectedID()+'&';
			}
			else
			{
				vals += 'vals[]=&';
			}
				
			if(this.columns[i]['id'] == params.col)
				found = true;
		}
				
		// Make the request
		new Ajax.Request('/columns/select', {
			  method: 'post',
			  parameters: cols+vals,
			  onSuccess: this.updateColumns.bind(this)
		});
	},
	
	updateColumns: function(transport)
	{
		var json = transport.responseText.evalJSON();	
		//var json = eval(transport.responseText);
		
		// Find the column and update the contents
		var found = false;
		for(var i=0; i < this.columns.length; i++)
		{
			// Clear all columns to the right of a selection
			if(found)
			{
				this.columns[i].emptyList();
				this.columns[i].setVisibility(false);
			}
			else
			{
				this.columns[i].setVisibility(true);
			}
			
			if(this.columns[i]['id'] == json.col)
			{
				this.columns[i].updateList(json.items);
				found = true;
			}
		}
		
		// Update the UI's count of the number of items
		if($('ItemCount'))
			$('ItemCount').update(json.count);
			
		this.resize();
		this.container.scrollLeft = this.surface.scrollWidth - this.container.getWidth();
	},
	
	resetColumns: function()
	{
		var params = '';
		
		if(this.surface.hasChildNodes())
		{
			// Order the Columns so the backend knows to ignore the default columns config
			for(var i=0; i < this.columns.length; i++)
			{
				if(i>0)
					params += '&';
					
				params += 'col[]='+this.columns[i]['id'];
			}
		}
		
		// Request the columns
		new Ajax.Request('/columns/load', {
			  method: 'post',
			  parameters: params,
			  onSuccess: this.loadColumns.bind(this)
		});
	},
	
	loadColumns: function(transport)
	{	
		var initialLoad = false;
		
		// Empty the element
		if ( this.surface.hasChildNodes() )
		{
			while ( this.surface.childNodes.length >= 1 )
			{
				this.surface.removeChild( this.surface.firstChild );
			}
		}
		else
			initialLoad = true;
		
		var json = transport.responseText.evalJSON();
		this.columns_config = json.columns;
		
		this.columns = new Array();
		this.columns_lookup = new Array();
		
		for(var i=0; i < this.columns_config.length; i++)
		{
			var col = new Column(this.columns_config[i]);
			
			this.columns.push(col);
			this.columns_lookup[this.columns_config[i]['id']] = col;
			
			this.surface.appendChild(col.surface);	
			col.resize();
			
			col.setVisibility( (i==0) );
		}
		
		// If this is the very first load then save what has come back from the AJAX request as the default config
		if(this.initial_columns == null)
			this.initial_columns = this.columns;
		
		if(!initialLoad)	
			this.resize();
		
		// Update the UI's count of the number of items
		if($('ItemCount'))
			$('ItemCount').update(json.count);
	},
	
	update: function()
	{		
		// Reorder the array of columns
		var elements = this.surface.childElements();
		this.columns = new Array();
		
		for(var i=0; i < elements.length; i++)
		{
			this.columns.push(this.columns_lookup[elements[i].id]);
		}
		
		this.resetColumns();
	}
}

/* ----- COLUMN OBJECT ----- */

var Column = Class.create();

Column.prototype = {
	name: null,
	id: null,
	surface: null,
	name_surface: null,
	list_container: null,
	list_surface: null,
	items: null,
	selected: null,
	items_lookup: null,
	
	initialize: function(params) {
		this.name = params.name;
		this.id = params.id;
		this.items = params.items; 
		this.items_lookup = new Array();
		
		this.surface = $(document.createElement('li'));
		this.surface.addClassName('column');
		this.surface.setAttribute('id', this.id);
		
		this.name_surface = $(document.createElement('div'));
		this.name_surface.addClassName('handle');
		this.name_surface.insert(this.name);
		this.surface.appendChild(this.name_surface);
		
		this.list_container = $(document.createElement('div'));
		this.list_container.addClassName('list');
		this.surface.appendChild(this.list_container);
		
		this.list_surface = $(document.createElement('ul'));
		this.list_container.appendChild(this.list_surface);
		
		this.updateList();
	},
	
	getSelectedID: function()
	{
		if(this.selected == 'All')
			return -1;
			
		return this.items_lookup[this.selected.replace('&amp;', '&')];
	},
	
	setVisibility: function(show)
	{
		if(show)
			this.surface.addClassName('hasSelection');
		else
			this.surface.removeClassName('hasSelection');
	},
	
	getColumnWidth: function()
	{
		if(this.surface.hasClassName('hasSelection'))
			return this.surface.getWidth() + parseInt(this.surface.getStyle('margin-right'));
		else
			return 0;
	},
	
	updateList: function(list)
	{
		if(list)
			this.items = list;
		
		this.emptyList();

		if(this.items)
		{
			this.items_lookup = new Array();
			
			// Add the 'All' option
			var item = $(document.createElement('li'));	
			item.insert("All");
			this.list_surface.appendChild(item);
			Event.observe(item, 'click', this.selectItem.bindAsEventListener(this));
			item.addClassName('odd');
			item.addClassName('all'); // Added this incase the 'All' should somehow be styled differently
		
			var count = 0; // we must use a seperate count variable to the array index as some are duplicates so odd/even wont work properly
		
			for(var i=0; i < this.items.length; i++)
			{
				if(this.items_lookup[this.items[i]['title']] == undefined)
				{
					this.items_lookup[this.items[i]['title']] = this.items[i]['id'];					

					var item = $(document.createElement('li'));	
					item.insert(this.items[i]['title']);
					this.list_surface.appendChild(item);
					Event.observe(item, 'click', this.selectItem.bindAsEventListener(this));

					if(count%2 == 1)
							item.addClassName('odd');
						else 
							item.addClassName('even');
							
					count++;
				}
				else
				{
					this.items_lookup[this.items[i]['title']] += ','+this.items[i]['id'];
					// console.log('dupe:- '+this.items[i]['title']);
				}
			}
		}
	},
	
	emptyList: function()
	{
		// Empty the element
		if ( this.list_surface.hasChildNodes() )
		{
	    while ( this.list_surface.childNodes.length >= 1 )
        this.list_surface.removeChild( this.list_surface.firstChild );       
		}
	},
	
	selectItem: function(e)
	{
		this.selected = e.target.innerHTML;
		
		document.fire("column:selectitem", {col: this.id, item: this.items_lookup[e.target.innerHTML]});
		
		// Update the list so only the selected item is highlighted
		var elements = this.list_surface.childElements();
		
		for(var i=0; i < elements.length; i++)
		{
			if(elements[i].innerHTML == e.target.innerHTML)
				elements[i].addClassName('selected');	
			else
				elements[i].removeClassName('selected');
		}
	},
	
	// Function that sets the height of the container for the list element
	resize: function() {
		// Calculate the height of the list element
		var height = this.surface.getHeight() - this.name_surface.getHeight();
		this.list_container.setStyle({height: height+'px'});
	}
}
