/*
	Class: URSPIN.ContentArea
*/
URSPIN.ContentArea = new Class({
	$URSPIN_isContentArea:true,

	userTabID: null,

	setUserTabID: function (id) {
		this.userTabID = id;
		this.setProperty('id', ['content-body-',id].join(''));
	},


	initialize: function (options) {
		this.userTabID = options['userTabID'];
		var contentID = ['content-body-', options['userTabID']].join('');
		var el = new Element('div', {'id': contentID,'class': 'content-body'});
		// this.setColsEqualHeight = this.setColsEqualHeightUnbound.bind(el);
		return $extend(el, this);
	},

	show: function () {
		this.addClass('content-body-selected');
		this.fireEvent('resize');
	},

	hide: function () {
		this.removeClass('content-body-selected');
	}

	// setColsEqualHeight: Class.empty,
	// setColsEqualHeightUnbound: Class.empty

});



/*
	Class: URSPIN.ColumnedContentArea
*/
URSPIN.ColumnedContentArea = URSPIN.ContentArea.extend({
	isContentLoaded: false,

	initialize: function (options) {
		var el = this.parent(options);
		options.numColumns = options.numColumns || 3;

		el.addClass(['content-body-', options.numColumns, 'col'].join(''));
		el.addClass(['content-body-', options.numColumns, 'col-', (options.colWidthStyle||'33-33-33')].join(''));

		// create columns
		el.columns = [];
		for (var i = 0; i < options.numColumns; i++) {
			el.columns[i] = new URSPIN.Column(i).injectInside(el);
		}

		this.cb = el.getElement('.cb') || new Element('div',{'class':'cb'}).injectInside(el);

		return $extend(el, this);
	},
	
	show: function () {
		this.parent();
		if (!this.isContentLoaded  && ($type(this.userTabID) != 'string' || !this.userTabID.test("^n\-"))) {
			this.loadContent();
		}
	},
	

	loadContent: function () {
		this.onLoadingStart();
		this.isContentLoaded = true;
		this.removeContents();
		this.xhr = this.xhr || new XHR({'onSuccess':this.onContentLoadComplete.bind(this),'onFailure':this.onContentLoadFailure.bind(this)});
		this.xhr.send('services/wt/user/', Object.toQueryString({'cmd':'getTabContent','userTabID':this.userTabID}));
	},


	moveModule: function (module, column, columnInnerPosition) {
		// console.log('content area: moveModule %o (%d, %d)', module, column, columnInnerPosition);

		this.addModule(module, column, columnInnerPosition, {'move':true});
	},

	addModule: function (module, column, columnInnerPosition, options) {
		options = options || {};

		// TODO default values of 'column' and 'columnInnerPosition' if out of range

		column = $chk(column) ? column : module.options.column;

		// balance adding of module if no column is specified
		// i.e. add module to the column with the least amount of modules
		if (!$chk(column)) {
			column = 0;
			// var mh = this.columns[0].getModules().length;
			// for (var i = this.columns.length - 1; i >= 0; i--) {
			// 	if (this.columns[i].getModules().length < mh) {
			// 		column = i;
			// 	}
			// }
		}

		columnInnerPosition = $chk(columnInnerPosition) ? columnInnerPosition : module.options.row;

		// console.log(module.options.title, column, columnInnerPosition);

		var col = this.columns[column];
		if ($defined(col)) {
			if (options.move) {
				col.moveModule(module, columnInnerPosition);
			} else {
				col.addModule(module, columnInnerPosition);
			}
		}
		module.refreshContent();
	},
	
	removeModule: function (module) {
		if (this.hasChild(module)) {
			var col = 0;
			for (col = 0; col < this.columns.length; col++) {
				if (this.columns[col].hasChild(module)) {
					break;
				}
			}

			this.columns[col].setStyle('display','none');
			module.remove();
			this.columns[col].setStyle('display','block');
		}
		// console.log('removeModule: userModuleID: %d', module.options.userModuleID);

		new XHR().send(
			'services/wt/user/',
			Object.toQueryString({
				'cmd':'updateModule',
				'op':'rm',
				'uMID':module.options.userModuleID
			}
		));

		URSPIN.Notify.undo([URSPIN.l10n.getString('ui.notify.module.removeprepend'), '"', module.options.title, '"', URSPIN.l10n.getString('ui.notify.module.removeappend')].join(''), function() {
			new XHR().send(
				'services/wt/user/',
				Object.toQueryString({
					'cmd':'updateModule',
					'op':'urm',
					'uMID':module.options.userModuleID
				}
			));
			this.addModule(module);
		}.bind(this));
		
	},

	// setColsEqualHeightUnBound: function () {
	// 	this.parent();
	// 	
	// 	if (!this.hasClass('content-body-selected')) {
	// 		return null;
	// 	}
	// 
	// 	// resize the columns to fill the height of the
	// 	// content area
	// 
	// 	// get the height of the tallest column 
	// 	var maxHeight = 0;
	// 	for (var i = 0; i < this.columns.length; i++) {
	// 		// clear the height style and the browser will resize the
	// 		// column to its minimum height (i.e. aggegrate height of
	// 		// its component elements)
	// 		this.columns[i].setStyle('height','');
	// 
	// 		if (this.columns[i].offsetHeight > maxHeight) {
	// 			maxHeight = this.columns[i].offsetHeight;
	// 		}
	// 	}
	// 
	// 	// if the maxHeight is less than the height of the visible
	// 	// area then resize to the columns to height of the visible area 
	// 
	// 	// var p = $('content-bodies').getStyle('padding-bottom').toInt();
	// 	// var p = 95;
	// 	// 
	// 	// var visibleHeight = window.getHeight() - this.getTop() - p;
	// 	// maxHeight = (maxHeight < visibleHeight) ? visibleHeight : maxHeight;		
	// 
	// 	// set the height of all the columns
	// 	
	// 	if (maxHeight > 0) {
	// 		for (var i = 0; i < this.columns.length; i++) {
	// 			this.columns[i].setStyle('height', maxHeight);
	// 		}
	// 	}
	// },
	
	// colNoHeight: function () {
	// 	for (var i = 0; i < this.columns.length; i++) {
	// 		this.columns[i].setStyle('height','');
	// 	}
	// },
	
	
	onContentLoadComplete: function (t, x) {
		var data = Json.evaluate(t);		
		// console.log('data loaded for content area (userTabID = %s)', this.userTabID);
		// console.dir({'content area data': data});

		this.onContentLoad(data['content']);

		this.onLoadingStop();
	},
	
	onContentLoadFailure: function (xhr) {
		// console.warn('could not load data for content area (userTabID = %s)', this.userTabID);
		this.isContentLoaded = false;
		this.onLoadingStop();
	},
	
	onContentLoad: function (contentRaw) {
		
		for (var i = 0; i < contentRaw.modules.length; i++) {
			var m = contentRaw.modules[i];
			// `moduleID`, `title`, `type`, `contentType`, `content`, `contentWidth`, `contentWidthUnit`, `contentHeight`, `contentHeightUnit`,
			// `userModuleID`, `column`, `row`
			var module = {
				'moduleID':m[0],
				'title':m[1],
				'type':m[2],
				'contentType':m[3],
				'content':m[4],
				'contentWidth':m[5],
				'contentWidthUnit':m[6],
				'contentHeight':m[7],
				'contentHeightUnit':m[8],
				'userModuleID':m[9],
				'column':m[10],
				'row':m[11],
				'minimized':m[12],
				// 'feedURI':m[13],
				'settings':m['s']
			};
			
			this.addModule(URSPIN.ModuleFactory.createModule(module));
			
			// if (module['type'] == 'feed') {
			// 	this.addModule(new URSPIN.FeedModule(module));
			// } else {
			// 	this.addModule(new URSPIN.Module(module));
			// }
		}
		
	},
	
	removeContents: function () {
		for (var i = 0; i < this.columns.length; i++) {
			this.columns[i].removeContents();
		}
	},
	
	onLoadingStart: function () {
		this.adopt(new Element('div',{'class':'content-body-throbber'}));
	},

	onLoadingStop: function () {
		this.getElements('.content-body-throbber').each(function (el) {
			el.remove();
		});
	}
	
	
});


/*
	Class: URSPIN.Column
*/
URSPIN.Column = new Class({
	columnNum: null,
	insideCol: null,
	
	initialize: function (columnNum) {
		this.columnNum = columnNum;
		// construct outer div
		var el = new Element('div', {'class':'col'});
		el.addClass(['col-', columnNum].join(''));
		
		// construct inner div, used for adding padding to columns without
		// affecting the width of the column
		this.insideCol = new Element('div',{'class':'col-inside'}).injectInside(el);

		// drag and drop events
		el.addEvents({
			'dragover': this.dragOver.bind(el),
			'leave': this.dragLeave.bind(el),
			'drop': this.drop.bind(el)
		});
		
		return $extend(el, this);
	},
	
	dragOver: function (dropEl, drag) {
		// console.log('dragover', this, arguments);
		var mods = this.getModules();;

		var i = this.getModuleDropIndex(drag.mouse.now.y, dropEl);


		if ($defined(mods[i])) {
			dropEl.wirePreview.injectBefore(mods[i]);
		} else {
			dropEl.wirePreview.injectInside(this.insideCol);
		}
	},
	
	dragLeave: function (dropEl, drag) {
		// console.log('leave');
		// if ($defined(dropEl.wirePreview.getParent())) {
		// 	dropEl.wirePreview.remove();
		// }
		dropEl.wirePreview.injectAfter(dropEl);
	},

	drop: function (dropEl, drag) {
		// console.log('drop', this, arguments);
		
		// clean up the dropped element before adding to column.
		// cleanUpDrag() is also called after the drop when the onComplete
		// fires for the dragged element.
		// That's ok, the second call is harmeless.
		dropEl.cleanUpDrag();

		this.moveModule(dropEl, this.getModuleDropIndex(drag.mouse.now.y), dropEl);
	},


	moveModule: function (module, position) {

		this.addModule(module, position);

		var modules = this.getElements('.mod');
		var newColModuleOrder = '';
		for (var i = 0; i < modules.length; i++) {
			newColModuleOrder = [newColModuleOrder, modules[i].options.userModuleID, '-'].join('');
		}
		module.movedTo(this.getParent().userTabID, this.columnNum, modules.indexOf(module), newColModuleOrder);
	},
	

	
	addModule: function (module, position) {
		
		var mods = this.getModules('.mod');
		
		if ($defined(mods[position])) {
			module.injectBefore(mods[position]);
			mods.splice(position, 0, module);
		} else if (position == -2 || !$chk(position)) {
			module.injectTop(this.insideCol);
			mods.push(module);
		} else {
			module.inject(this.insideCol);
			mods.push(module);
		}

		module.options.column = this.columnNum;
		module.options.row = mods.indexOf(module);
		
		this.getParent().fireEvent('resize');

		// console.log(module);

		return module;
	},

	getModules: function () {
		// this.modules = this.modules || this.getElements('.mod');
		// return this.modules;
		return this.getElements('.mod');
	},
	
	// determines the index of the module the cursor is over.
	// if the cursor is lower than half the height of the module
	// then return the index of the next one
	getModuleDropIndex: function (h, m) {
		var mods = this.getModules();
		for (var i = 0; i < mods.length; i++) {
			if (mods[i] != m) {
				if (h < (mods[i].getTop() + (mods[i].offsetHeight / 2))) {
					return i;
				}
			}
		}
		return -1;
	},
	
	removeContents: function () {
		this.insideCol.empty();
	}

});