/**
 * This file is copyright Four Point Two Software Ltd.
 *
 * mikey@fourpointtwo.co.nz
 * www.fourpointtwo.co.nz
 */

function $E(selector)
{
	return document.getElement(selector);
}


/*** The Widget base class which other widgets extend ***/

var Widget = new Class({

	ajax: null,
	params: null,
	className: null,
	domNode: null,
	customisePanel: null,

	initialize: function(className, params)
	{
		this.className			= className;
		this.params					= params;
		this.domNode				= $(this.getId());
		this.domNode.widget = this;

		this.initCustomisePanel();
	},

	initCustomisePanel: function() {

		this.domNode.getChildren('.editButton').each(function(item){

			this.customisePanel			= this.domNode.getElement('.moduleCustomisePanel');
			this.customisePanel.fx	= new Fx.Slide(this.customisePanel, {duration: 100});

			this.customisePanel.fx.hide();
			this.customisePanel.setStyle('display', 'block');

			item.addEvent('click', this.editClicked.bindWithEvent(this));

			this.customisePanel.getChildren('a#save').each(function(item){
				item.addEvent('click', this.saveClicked.bindWithEvent(this));
			}, this);
			this.customisePanel.getChildren('a#cancel').each(function(item){
				item.addEvent('click', this.cancelClicked.bindWithEvent(this));
			}, this);
		}, this);

	},

	editClicked: function(event) {
		this.customisePanel.fx.toggle();
		event.stop();
	},

	cancelClicked: function(event) {
		this.customisePanel.fx.slideOut();
		event.stop();
	},

	saveClicked: function(event) {
		this.customisePanel.fx.slideOut();
		this.saveConfig();
		event.stop();
	},

	saveConfig: function()
	{
		this.ajax = new Request({	url: '/widget/saveconfig.php?name='+this.getId()
															, method: 'post'
															, data: this.serialize()
															, onComplete: this.saveComplete.bind(this)}
														);
		this.ajax.addEvent('success', this.saveComplete.bindWithEvent(this));
		this.ajax.send();
	},

	saveComplete: function(responseText, responseXML)
	{
		this.ajax = null;
	},

	getStartupParams: function()
	{
		return {'class': this.className, 'params': this.params};
	},

	serialize: function()
	{
		alert('serialize not implemented');
		return this.toString();
	},

	getId: function()
	{
		return this.className+'_'+this.params.replace(' ', '+');
	},

	isInStickySlot: function()
	{
		return (this.domNode.getParent().id == 'stickySlot');
	},

	repaint: function()
	{
	}
});


/*** ArticleWidget ***/

var ArticleWidget = new Class({

	Extends: Widget,

	STICKY_NUM_ARTICLES: 4,

	initialize: function(className, params)
	{
		this.parent(className, params);

		this.customisePanel.getElements('input, select').each(function(input){
			input.addEvent('change', this.repaint.bindWithEvent(this));
			input.addEvent('click', this.repaint.bindWithEvent(this));
		}, this);

		if(this.isInStickySlot()) {
			this.repaint(null);
		}
	},

	repaint: function(event)
	{
		var displayImages	= this.customisePanel.getElement('input.images').checked;
		var numShow				= this.customisePanel.getElement('select.count').value;
		var numShown			= 0;

		if(this.isInStickySlot()) {
			displayImages = false;
			numShow				= this.STICKY_NUM_ARTICLES;
			this.domNode.getElement('.editButton').setStyle('display', 'none');
		} else {
			this.domNode.getElement('.editButton').setStyle('display', 'inline');
		}

		if(displayImages) {
			this.domNode.addClass('topStoriesMod');
			this.domNode.removeClass('textOnly');
		} else {
			this.domNode.removeClass('topStoriesMod');
			this.domNode.addClass('textOnly');
		}

		this.domNode.getElements('li').each(function(item){
			if(numShown++ < numShow) {
				this.showItem(item, numShown, displayImages);
			} else {
				this.hideItem(item);
			}
		}, this);
	},

	showItem: function(item, numShown, displayImages)
	{
		item.set('slide', {duration: 200});

		if(item.hasClass('hide')) {
			item.removeClass('hide');
		}
		if(numShown == 1) {
			item.addClass('lead');
		} else {
			item.removeClass('lead');
		}
		if(displayImages) {
			var image = item.getElement('img');
			if(image.src.length == 0) {
				image.src = image.id;
			}
		}
		item.slide('show');
	},

	hideItem: function(item)
	{
		item.set('slide', {duration: 200});

		item.slide('hide');
	},

	serialize: function()
	{
		return JSON.encode({displayImages:	this.customisePanel.getElement('input.images').checked
											, numShow:				this.customisePanel.getElement('select.count').value});
	}
});


/*** FeaturedWidget ***/

var FeaturedWidget = new Class({

	Extends: Widget,
	imageCount: 0,
	currentImage: 0,
	imageDivs: null,
	periodical: null,

	initialize: function()
	{
		this.parent('FeaturedWidget', 'none');

		this.imageDivs = new Array();

		this.domNode.getElements('div.carouselImages div.item').each(function(div){
			this.imageDivs[this.imageCount] = div;
			if(div.hasClass('hide')) {
				div.setStyle('opacity', 0);
				div.removeClass('hide');
			}
			this.domNode.getElements('#carousel'+this.imageCount).addEvent('click', this.setImage.bindWithEvent(this));
			this.imageCount++
		}, this);


		this.periodical = this.rotate.periodical(5000, this);
	},

	setImage: function(event)
	{
		$clear(this.periodical);

		this.imageDivs[this.currentImage%this.imageCount].tween('opacity', 0);
		$('carousel'+(this.currentImage%this.imageCount)).removeClass('highlight');
		this.currentImage = event.target.rel;
		this.imageDivs[this.currentImage].tween('opacity', 1);
		$('carousel'+(this.currentImage%this.imageCount)).addClass('highlight');

		this.periodical = this.rotate.periodical(5000, this);
		event.stop();
	},

	rotate: function()
	{
		$('carousel'+(this.currentImage%this.imageCount)).removeClass('highlight');
		this.imageDivs[this.currentImage++%this.imageCount].tween('opacity', 0);
		this.imageDivs[this.currentImage%this.imageCount].tween('opacity', 1);
		$('carousel'+(this.currentImage%this.imageCount)).addClass('highlight');
	},

	repaint: function()
	{
		//if(this.isInStickySlot()) {
		//	this.domNode.getElement('.carouselImages').addClass('hide');
		//} else {
		//	this.domNode.getElement('.carouselImages').removeClass('hide');
		//}
	}
});

/*** TagWidget ***/

var TagWidget = new Class({

	Extends: ArticleWidget,

	repaint: function(event)
	{
		var showNews 			= this.customisePanel.getElement('input.news').checked;
		var showReviews		= this.customisePanel.getElement('input.reviews').checked;
		var displayImages	= this.customisePanel.getElement('input.images').checked;
		var numShow				= this.customisePanel.getElement('select.count').value;
		var numShown			= 0;

		if(this.isInStickySlot()) {
			displayImages = false;
			numShow				= this.STICKY_NUM_ARTICLES;
			this.domNode.getElement('.editButton').setStyle('display', 'none');
		} else {
			this.domNode.getElement('.editButton').setStyle('display', 'inline');
		}

		if(displayImages) {
			this.domNode.addClass('topStoriesMod');
			this.domNode.removeClass('textOnly');
		} else {
			this.domNode.removeClass('topStoriesMod');
			this.domNode.addClass('textOnly');
		}

		this.domNode.getElements('li').each(function(item){
			if(item.hasClass('News')) {
				if(showNews && numShown++ < numShow) {
					this.showItem(item, numShown, displayImages);
				} else {
					this.hideItem(item);
				}
			} else {
				if(showReviews && numShown++ < numShow) {
					this.showItem(item, numShown, displayImages);
				} else {
					this.hideItem(item);
				}
			}
		}, this);
	},

	serialize: function()
	{
		return JSON.encode({showNews:				this.customisePanel.getElement('input.news').checked
											, showReviews:		this.customisePanel.getElement('input.reviews').checked
											, displayImages:	this.customisePanel.getElement('input.images').checked
											, numShow:				this.customisePanel.getElement('select.count').value});
	}
});

/**** MySortables ***/
/**
 * TODO: See if we can't using the Mootools Sortables class.
 * TODO: Fix slight shifting of surrounding li's when dragging starts. (Clone probably has slightly incorrect dimensions)
 */
var MySortables = new Class({

	Extends: Sortables,

	getClone: function(event, element){
		var el = new Element('li');

		el.setStyles({'width': element.getStyle('width')
								, 'height': element.getStyle('height')
								, 'background-color': '#4A5057'
								, 'margin': element.getStyle('margin')
								, 'border': '1px solid #fff'
								, 'visibility': 'hidden'
							})
		el.inject(this.list)
		el.position(element.getPosition(element.getOffsetParent()));
		return el;
	},

	getDroppables: function(){
		var droppables = this.list.getChildren();
		if (!this.options.constrain) droppables = this.lists.concat(droppables).erase(this.list);
		return droppables.erase(this.clone).erase(this.element);
	},

	insert: function(dragging, element){
		var where = 'inside';

		if (this.lists.contains(element)){
			this.list = element;
			this.drag.droppables = this.getDroppables();
		} else {
			where = this.clone.getAllPrevious().contains(element) ? 'before' : 'after';
		}
		this.clone.inject(element, where);

		this.fireEvent('sort', [this.clone, this.element]);
	},

	start: function(event, element){

		if (!this.idle) return;
		this.idle = false;
		this.element = element;
		this.fireEvent('pre', this.element);
		this.opacity = element.get('opacity');
		this.element.position(this.element.getPosition(this.element.getOffsetParent())).setStyles({ 'position':'absolute','z-index':'999', 'opacity': this.options.opacity});

		this.list = element.getParent();
		this.clone = this.getClone(event, element);

		this.drag = new Drag.Move(this.element, {
			snap: this.options.snap,
			container: this.options.constrain && this.element.getParent(),
			droppables: this.getDroppables(),
			onSnap: function() {

				event.stop();
				this.clone.setStyle('visibility', 'visible');
				this.fireEvent('start', [this.clone, this.element]);
			}.bind(this),
			onEnter: this.insert.bind(this),
			onCancel: this.reset.bind(this),
			onComplete: this.end.bind(this)
		});

		this.clone.inject(this.element, 'before');
		this.drag.start(event);
	},

	end: function(){

		this.drag.detach();

		this.element.inject(this.clone, 'before');

		if (this.effect){
			var pos = this.element.computePosition(this.clone.getPosition(this.element.offsetParent));
			this.effect.element = this.element;
			this.effect.start({
				top: pos.top,
				left: pos.left,
				opacity: this.opacity
			}).chain(this.reset.bind(this));
		} else {
			this.reset();
		}
	},

	reset: function(){

		this.idle = true;
		this.element.setStyles({ 'position':'relative','z-index':'0', 'top':'0', 'left':'0'});
		this.clone.destroy();
		this.fireEvent('complete', this.element);
	}

});


/*** WidgetList ***/

var WidgetList = new Class({

	Extends: Widget,

	sortable: null,

	initialize: function(className, params)
	{
		if(!$(className+'_'+params)) {
			return;
		}

		this.parent(className, params);

		this.sortable = new MySortables('ul.modList', {handle: '.dragHandle', clone: true, revert: true, opacity:1, snap: 20});
		this.sortable.addEvent('complete', this.handleDragComplete.bindWithEvent(this));
		this.sortable.addEvent('pre', this.handleDragStart.bindWithEvent(this));

		this.customisePanel = $('customisePanel');

		document.getElement('#customiseButton').addEvent('click', function(event) {
			this.customisePanel.setStyles({display: 'block'});
			event.stop();
		}.bindWithEvent(this));

		document.getElement('#customisePanel #cancel').addEvent('click', function(event) {
			this.customisePanel.setStyles({display: 'none'});
			event.stop();
		}.bindWithEvent(this));

		document.getElement('#customisePanel #save').addEvent('click', function(event) {
			this.customisePanel.setStyles({display: 'none'});
		}.bindWithEvent(this));

		this.customisePanel.getElement('#addOwn').addEvent('click', this.handleAddOwn.bindWithEvent(this));
	},

	handleDragStart: function (element)
	{
		element.getElements('.item a').each(function(atag){
			atag.addEvent('click', function(e){
				e.stop();
			});
		});


		if($$('#stickySlot li.module').length == 1 && element.parentNode.id != 'stickySlot') {
			this.sortable.removeLists($('stickySlot'));
		}
	},

	handleDragComplete: function (element)
	{
		element.getElements('.item a').each(function(atag){
			atag.removeEvents();
		});

		this.sortable.addLists($('stickySlot'));
		element.widget.repaint();
		this.saveConfig();
	},

	handleAddOwn: function (event)
	{
		var checkbox = new Element('input', { 'type':    'checkbox'
																				, 'name':    'input_TagWidget_'+document.getElement("#ownTagList").value.replace(' ', '+')
																				, 'value':   1
																				, 'checked': 'checked'});
		var label = new Element('label', {'html': document.getElement("#ownTagList").value});
		var li = new Element('li');

		checkbox.inject(label, 'top');
		label.inject(li);

		li.inject(document.getElement('#customisePanel #ownWidgets'), 'top');
		event.stop();
	},

	serialize: function()
	{
		var config = {};

		$$('ul.modList').each(function(list){
			config[list.id] = new Array();

			list.getElements('li.module').each(function(widget){
				config[list.id].push(widget.widget.getStartupParams());
			}, this);

		}, this);

		return JSON.encode(config);
	}

});
