function Library(url, libraryId)
{
	this.url = url;
	this.libraryId = libraryId;
}

Library.prototype.toggleCategory = function (categoryId, aElement)
{
	Element.extend(aElement);
	var cat = $('category_' + this.libraryId + '_' + categoryId);
	var span = aElement.down('span.libExpand');
	var openCats = readCookie('open_library_' + this.libraryId);
	if(openCats==null)
	{
		openCats = new Array();
	}
	else
	{
		openCats = openCats.evalJSON();
	}
	
	if(!aElement.hasClassName('libExpanded'))
	{
		aElement.addClassName('libExpanded');
		span.update('(collapse this category)');
		openCats.push(categoryId);
	}
	else
	{
		aElement.removeClassName('libExpanded');
		span.update('(expand this category)');
		for(var x=0; x<openCats.length; x++)
		{
			if(openCats[x]==categoryId)
			{
				openCats.splice(x, 1);
			}
		}
	}
	
	createCookie('open_library_' + this.libraryId, openCats.toJSON(), 1);
	
	if(cat.down('li.libLoading'))
	{
		new Ajax.Request(this.url, {
			'method': 'get',
  			parameters: { 'libraryId': this.libraryId, 'categoryId': categoryId },
  			'onSuccess': function(transport) { cat.update(transport.responseText);this.observePodcastLinks(categoryId); }.bind(this)
		});
	}
	
	cat.toggle();
}

Library.prototype.observePodcastLinks = function (categoryId)
{    
    var links = $$('#category_'+this.libraryId+'_'+categoryId+' a.podcastLink');
    for(var x=0;x<links.length;x++)
    {
    	new PodcastInfo(links[x]);
    }
}

Library.prototype.observePodcastLinks2 = function ()
{    
    var links = $$('#selecTable a.podcastLink');
    for(var x=0;x<links.length;x++)
    {
    	new PodcastInfo(links[x]);
    }
}

function PodcastInfo(linkElement)
{
	this.link = linkElement;
	this.infoTimer = null;
	this.podcastInfo = null;
	
	this.mouseOverHandler = function(event){
		this.startPodcastInfoTimer(event);
		//event.stop();
		return false;
    }.bindAsEventListener(this);
    this.mouseOutHandler = function(event){
    	this.clearPodcastInfoTimer(event);
    }.bindAsEventListener(this);
    
    this.link.observe('mouseenter',this.mouseOverHandler);
    this.link.observe('mouseleave',this.mouseOutHandler);
} 

PodcastInfo.prototype.showPodcastInfo = function(event)
{
	Event.extend(event);
	var link = Event.element(event);
	if(link.nodeName!='A')
	{
		link = link.up();
	}
	
	link.stopObserving('mouseenter',this.mouseOverHandler); // 'mouseenter',this.mouseOverHandler
	this.podcastInfo = new Control.Window(link, {  
     position: 'mouse', 
     hover: true,  
     offsetLeft: 40,  
     className: 'podcastInfo',
     iframeshim: false,
     iframe: false
	});
	this.podcastInfo.open(event);
}

PodcastInfo.prototype.startPodcastInfoTimer = function(event)
{
	var link = Event.element(event);
	if(link.nodeName!='A')
	{
		link = link.up();
	}
	link.title = '';
	var newEvent = Object.clone(event);
	var delay = function() { this.showPodcastInfo(newEvent); }.bind(this);
	this.infoTimer=setTimeout(delay, 600);
}

PodcastInfo.prototype.clearPodcastInfoTimer = function(event)
{
	var link = Event.element(event);
	try
	{
		clearTimeout(this.infoTimer);
	} catch(err) { }
	if(this.podcastInfo!=null)
	{
		/*
		 This lot below is a bit of a hack fix. For some reason the window wont close the first time when
		 you move away from the element, maybe because we force open in showPodcastInfo() so we have to
		 hide and close here
		*/
		this.podcastInfo.dontShowYet = true;
		
		//this.podcastInfo.container.hide();
		this.podcastInfo.close(event); // I don't think this method fires properly poss window.js doesnt think it's open
		
		Event.element(event).stopObserving('mouseleave',this.mouseOutHandler);
	}
}

var basketNotifier = new function()
{
	this.listeners = [];

	this.addBasketListener = function(listener)
	{
		this.listeners.push(listener);
	};
	
	this.notifyItemAdded = function(podcastId, result)
	{
		for(var x=0;x<this.listeners.length;x++)
		{
			this.listeners[x].itemAdded(podcastId, result);
		}
	};
	
	this.notifyItemRemoved = function(podcastId, result)
	{
		for(var x=0;x<this.listeners.length;x++)
		{
			this.listeners[x].itemRemoved(podcastId, result);
		}
	};
}

function Basket(podcastId, containingElement)
{
	this.podcastId = podcastId;
	this.containingElement = containingElement;
	this.freePurchase = false;
	this.addAccountHtml = '<form action="/basket/addAccount" method="post" class="addForm"><fieldset><legend>Add this podcast to your basket</legend><input type="hidden" name="course" value="'+podcastId+'"/><input type="submit" value="Add to Account" title="add this podcast to your account" /></fieldset></form>';
	this.inAccountHtml = '<em class="libPurchased" title="the podcast has been added to your account">added to &ldquo;<a href="/cpd/seekToCourse/id/'+podcastId+'#tab">My Account</a>&rdquo;</em>';
	this.addHtml = '<form class="addForm" action="/basket/add" method="post"><fieldset><legend>Add this podcast to your basket</legend><input type="hidden" value="'+podcastId+'" name="course" /><input type="submit" value="Add to Basket" title="add this podcast to your basket" /></form>';
	this.loadingHtml = '<span class="libLoading">[MSG]</span>';
	this.removeHtml = '<form class="removeForm" action="/basket/remove" method="post"><fieldset><legend>Remove this podcast from your basket</legend><input type="submit" value="Remove" title="remove this podcast from your basket" /></form>';

	basketNotifier.addBasketListener(this);
}

Basket.prototype.itemAdded = function(podcastId, result)
{
	if(podcastId==this.podcastId)
	{
		this.containingElement.update(this.removeHtml);
		this.observeRemove(result.basketId);
	}
}

Basket.prototype.itemRemoved = function(podcastId, result)
{
	if(podcastId==this.podcastId)
	{
		this.insertAdd();
	}
}

Basket.prototype.observeAdd = function()
{
	var form = this.containingElement.down('form.addForm');
	if(!form) return;
	form.observe('submit',function(event) { this.addItem(Event.element(event)); event.stop(); }.bind(this));
}

Basket.prototype.addItem = function(form)
{
	form.hide();
	this.showLoading('Adding...');
	form.request({
	 evalJSON: true,
	 onSuccess: function(transport) { this.complete(transport.responseText.evalJSON()); }.bind(this),
	 onFailure: function(transport) { this.displayBasketError('Add to basket/account failed, could not communicate with server.');this.failAdd(); }.bind(this)
	});
}

Basket.prototype.failAdd = function()
{
	var add = this.containingElement.down('form.addForm');
  add.show();
	this.removeLoading();
}

Basket.prototype.displayBasketError = function(message)
{
	var errorWin = new Control.Modal(null, {
	 overlayOpacity: 0.75, 
     className: 'basketErrorModal',
     iframe: false,
     iframeshim: false
	});
	errorWin.container.insert(message);
	var closeLink = new Element('a', { 'class': 'closeLink', href: '#' }).update("Close");
	errorWin.container.insert(closeLink);
	closeLink.observe('click', function(event) { 
		errorWin.close(event);
		errorWin.destroy(); 
		event.stop();	
	}.bind(errorWin));
	errorWin.position();
	errorWin.open();
}

Basket.prototype.complete = function(result)
{
	if(result.action=='add')
	{
		if(result.status=='success')
		{
			basketNotifier.notifyItemAdded(this.podcastId, result);
		}
		else
		{
			this.displayBasketError(result.reason);
			this.failAdd();
		}
	}
	else if(result.action=='add account')
	{
		if(result.status=='success')
		{
			this.containingElement.update(this.inAccountHtml);
		}
		else
		{
			this.displayBasketError(result.reason);
			this.failAdd();
		}
	}
	else if(result.action=='remove')
	{
		if(result.status=='success')
		{
			basketNotifier.notifyItemRemoved(this.podcastId, result);
		}
		else
		{
			this.displayBasketError(result.reason);
			this.failRemove();
		}
	}
	
	if(result.status=='success' && result.items!=undefined)
	{
		// update items in basket count
		var itemCount = $('basketItemCount');
		if(itemCount)
		{
			itemCount.update(result.items + ' item' + (result.items!=1?'s':''));
		}
		
		if(result.items==0)
		{
			new Effect.Fade('checkOutBox', { duration: 0.5 });
		}
		else
		{
			if(!$('checkOutBox').visible())
			{
				$('checkOutBox').show();
				new Effect.Pulsate('checkOutBox', { pulses: 3, duration: 1 });
			}
		}
	}
}

Basket.prototype.observeRemove = function(itemId)
{
	var form = this.containingElement.down('form.removeForm');
	if(!form) return;
	form.observe('submit', function(event) {
		this.removeItem(itemId, Event.element(event));
		event.stop(); 
	}.bind(this));
}

Basket.prototype.removeItem = function(itemId, form)
{
	form.hide();
	this.showLoading('Removing...');
	form.request( {
				parameters: { 'item': itemId },
				onSuccess: function(transport) { this.complete(transport.responseText.evalJSON()); }.bind(this),
				onFailure: function(transport) { 
					this.displayBasketError('Remove from basket failed, could not communicate with server.');
					this.failRemove(); 
				}.bind(this)
			});
}

Basket.prototype.failRemove = function()
{
	var remove = this.containingElement.down('form.removeForm');
	this.removeLoading();
	remove.show();
}

Basket.prototype.showLoading = function(message)
{
	this.containingElement.insert({bottom: this.loadingHtml.replace('[MSG]', message)});
}

Basket.prototype.removeLoading = function()
{
	var loading = this.containingElement.down('.libLoading');
	if(loading) loading.remove();
}

Basket.prototype.insertAdd = function()
{
	if(this.freePurchase)
	{
		this.containingElement.update(this.addAccountHtml);
	}
	else
	{
		this.containingElement.update(this.addHtml);
	}
	this.observeAdd();
}

Basket.prototype.insertRemove = function()
{
	this.containingElement.update(this.removeHtml);
	this.observeRemove();
}

Event.observe(window, 'load', function()
{
	setupLibraryDescriptionEvents();
});

function setupLibraryDescriptionEvents()
{
	$$('.editDescription').invoke('observe', 'click', function(event)
	{
		event.stop();
		var id = $(this).up().up().up().up().up().id.replace('library_', '');
		var descriptionContainer = $(this).up().up().up().up();

		new Ajax.Request(genUrl('/course/libraryDescription'),
		{
			method: 'post',
			parameters: { id: id },
			onSuccess: function(transport)
			{
				descriptionContainer.update(transport.responseText);
				setupLibraryDescriptionEditEvents(id, descriptionContainer);
			}
		});
	});
}

function setupLibraryDescriptionEditEvents(id, descriptionContainer)
{
	if($('cancel_' + id) != undefined)
	{
		$('cancel_' + id).observe('click', function(event)
		{
			event.stop();
			new Ajax.Request(genUrl('/course/libraryDescription'),
			{
				method: 'get',
				parameters: { id: id },
				onSuccess: function(transport)
				{
					descriptionContainer.update(transport.responseText);
					setupLibraryDescriptionEvents();
				}
			});
		});
	}

	$(descriptionContainer).down('form').observe('submit', function(event)
	{
		event.stop();
		$(this).request(
		{
			onSuccess: function(t)
			{
				descriptionContainer.update(t.responseText);
				setupLibraryDescriptionEvents();
			}
		});
	});
}

