/*
Section: urspin.tab.js
*/

URSPIN.TabFactory = {
	newTabCount: 0,

	newTab: function (options) {
		options = options || {};
		options.userTabID = options.userTabID || ['n-', this.newTabCount].join('');
		options.title = options.title || 'ui.tabbar.tab.title.default';

		var tab = null;

		if (options.tabTypeID == 1 && !options.modules) {
			tab = new URSPIN.Tab(options);
		} else {
			tab = new URSPIN.ModuleTab(options);
		}

		this.newTabCount++;

		return tab;

	}
};


/*
	Class: URSPIN.Tab
*/
URSPIN.Tab = new Class({

	contentArea: null,
	isContentLoaded: false,
	
	options: {
		'userTabID':null,
		'title':null,
		'iconImgSrc': null,
		'removable':true,
		'renamable':false,
		'sharable':false,
		'customizable':false
    },

	displayTitle: null,

	setUserTabID: function (id) {
		this.options.userTabID = id;
		this.setProperty('id', ['tab-', tab.options.userTabID].join(''));
		if (this.contentArea) {
			this.contentArea.setUserTabID(id);
		}
	},

	initialize: function (options) {
		this.setOptions(options);

		var el = new Element('div', {'id': ['tab-', this.options.userTabID].join(''), 'class':'tab','href':'javascript:void(0);'});

		if (this.options.title) {
			this.displayTitle = (this.options.title.test('^ui\.'))? URSPIN.l10n.getString(this.options.title) : this.options.title;
		}

		this.options.iconImgSrc = ['a/images/tab_bar/icons/', (this.options.iconImgSrc || 'default.png')].join('');
		if($defined(this.options.iconImgSrc)) {
			el.adopt(new Element('div', {'class':'tab-icn-wrap'}).setStyle('background-image', ['url(\'', this.options.iconImgSrc, '\')'].join('')));
		}

		var x = new Element('div',{'class':'tab-title'});
		el.adopt(x);

		var title = new Element('div', {'class':'tab-txt-wrap'}).setText(this.displayTitle);
		x.adopt(title);

		el.setProperty('title', this.displayTitle);


		var tabMenuBtn = new Element('div',{'class':'tab-menu-button'});
		x.adopt(tabMenuBtn);
		if (this.options.removable && !this.options.renamable && !this.options.sharable && !this.options.customizable) {
			tabMenuBtn.addClass('tab-menu-button-remove-only');
		}

		
		tabMenuBtn.addEvent('mousedown', function (e) {
			if (this.options.removable && !this.options.renamable && !this.options.sharable && !this.options.customizable) {
				this.removeFromTabManager();
				return;
			}

			if ($defined(this.menu) && this.menu.getParent()) {	this.menu.remove(); }

			var menuItems = [];
			if (this.options.customizable) {
				menuItems.push({
					'title':URSPIN.l10n.getString('ui.tabbar.tab.menu.customize'),
					'subMenu':[
						{'title':'sub1','onClick':null},
						{'title':'sub2','onClick':null}
					]
				});
			}
			
			if (this.options.renamable) {
				menuItems.push({
					'title':URSPIN.l10n.getString('ui.tabbar.tab.menu.rename'),
					'onClick':this.startUserRename.bind(el)
				});
			}
			
			if (this.options.removable) {
				menuItems.push({
					'title':URSPIN.l10n.getString('ui.tabbar.tab.menu.remove'),
					'onClick':function (e) {this.removeFromTabManager();}.bindWithEvent(el)
				});
			}
			
			
			// if (this.options.resetable) {
			// 	menuItems.push({
			// 		'title':URSPIN.l10n.getString('ui.tabbar.tab.menu.reset'),
			// 		'onClick':null
			// 	});
			// }
			// if (this.options.sharable) {
			// 	menuItems.push({
			// 		'title':URSPIN.l10n.getString('ui.tabbar.tab.menu.share'),
			// 		'onClick':null
			// 	});
			// }			
			this.menu = new URSPIN.Webtop.Menu({'class':'tab-menu', 'menuItems': menuItems});

			var coord = tabMenuBtn.getCoordinates();
			this.menu.show({'left':coord.left,'top':coord.bottom});
			e.stopPropagation();
		}.bindWithEvent(el));


		return $extend(el, this);
	},
	
	startUserRename: function (e) {
		// console.log('startUserRename', arguments);

		var txtWrap = this.getElement('.tab-txt-wrap');

		this.$URSPINinput = new Element('input',{'type':'text','value':txtWrap.getText()});
		this.$URSPINinput.addEvent('keypress', function (e) {
			if (e.code == "13") { // TODO esc and tab
				this.stopUserRename();
			}
		}.bindWithEvent(this));
		this.$URSPINinput.addEvent('blur', this.stopUserRename.bind(this));

		txtWrap.empty();
		txtWrap.adopt(this.$URSPINinput);
		this.$URSPINinput.focus();
		this.$URSPINinput.select();
	},

	stopUserRename: function () {
		var newTitle = this.$URSPINinput.value;
		this.$URSPINinput.removeEvents('keypress');
		this.$URSPINinput.removeEvents('blur');
		this.$URSPINinput.remove();
		this.$URSPINinput = null;
		this.getElement('.tab-txt-wrap').setText(newTitle);
		// TODO re-center title

		if (this.hasClass('tab-selected')) {
			var t = this.getElement('.tab-title');
			t.setStyle('margin-left', -((t.getElement('.tab-txt-wrap').offsetWidth) / 2) - 2);
		}

		if (newTitle != this.getTitle()) {
			new XHR().send('services/wt/user/', Object.toQueryString({
				'cmd':'updateTabTitle',
				'utid':this.options.userTabID,
				'nt':newTitle
			}));
			this.displayTitle = newTitle;
		}
		


	},
	
	
	createContentArea: function (options) {
		this.contentArea = this.contentArea || new URSPIN.ContentArea(this.options).injectInside($('content-bodies'));
		return this.contentArea;
	},
	
	getID: function () {
		return this.options.userTabID;
	},
	
	getTitle: function () {
		return this.displayTitle;
	},
	
	setTitle: function (title) {
		if (title) {
			this.displayTitle = (title.test('^ui\.'))? URSPIN.l10n.getString(title) : title;
		}
		
		this.getElement('.tab-txt-wrap').setText(this.displayTitle);
	},
	
	getTabManager: function () {
		// go up the ancestor tree looking for this tab's tab manager
		// should only go up 1 or 2 levels
		var manager = this.getParent();
		while ($defined(manager)) {
			if (manager.$URSPIN_isTabManager) {
				return manager;
			}
			if ($type(manager.getParent) == 'function') {
				manager = manager.getParent();
			} else {
				break;
			}
		}
		
		return null;
	},

	isSelected: function () { return this.hasClass('tab-selected'); },

	open: function (dontRecord) {
		if (this.hasClass('tab-selected')) {
			return;
		}
		// console.info('open', this);
		var t = this.getElement('.tab-title');
		t.setStyle('visibility', 'hidden');

		var w = t.getElement('.tab-txt-wrap');
		if (this.options.renamable) {
			w.addClass('renamble');
			// console.log('add mousedown', w);
			w.addEvent('mousedown', function (e) {
				e.stop();
				this.startUserRename.call(this);
			}.bindWithEvent(this));
		}

		w.setText(this.displayTitle);

		this.removeClass('droppable');
		this.addClass('tab-selected');
		t.setStyle('margin-left', -((w.offsetWidth) / 2) - 2);
		t.setStyle('visibility', 'visible');

		this.getContentArea().show();

		document.title = [this.getTitle(), ' - ', URSPIN.l10n.getString('ui.title')].join('');
	},

	close: function () {
		// console.info('close', this);
		if (this.contentArea) {
			this.contentArea.hide();
		}
		this.removeClass('tab-selected');
		this.addClass('droppable');
	
		
		var t = this.getElement('.tab-title');
		t.setStyle('visibility', 'hidden');
		t.setStyle('margin-left', 0);
		
		var w = this.getElement('.tab-txt-wrap');
		// console.log('remove mousedown', w);
		w.removeEvents('mousedown');
		// w.removeEvents();
		w.removeClass('renamble');		

		w.setStyle('position','absolute');
		// trim title
		var wid = w.offsetWidth;
		while (w.offsetWidth > t.offsetWidth) {
			var title = w.getText();
			w.setText([title.substring(0, title.length - 2), URSPIN.l10n.getString('ui.tabbar.tab.title.elipse')].join(''));
			wid = w.offsetWidth;
		}
		w.setStyle('position','');

		t.setStyle('visibility', 'visible');
	},
	
	removeFromTabManager: function () {
		var manager = this.getTabManager();
		if ($defined(manager)) {
			manager.removeTab(this);
		}
	},
	
	removeSelfAndRelated: function () {
		this.remove();
		// console.log('removeSelfAndRelated', this, this.contentArea);
		if (this.contentArea && this.contentArea.getParent()) {
			this.contentArea.remove();
			this.contentArea = null;
		}
	},
	
	getContentArea: function () {
		if (!this.contentArea) {
			this.createContentArea();
		}

		return this.contentArea;
	}
	


});
URSPIN.Tab.implement(new Options);

/*
	Class: URSPIN.ModuleTab
*/
URSPIN.ModuleTab = URSPIN.Tab.extend({

	options: {
		'numColumns':3,
		'modules':null,
		'renamable':true,
		'sharable':true,
		'customizable':true
    },

	initialize: function (options) {
		
		
		this.setOptions(options);

		var el = this.parent(options);
		


		el.addClass('tab-with-sub-tabs');
		el.addClass('droppable');


		$extend(el, this);
	
		// drag and drop events
		el.addEvents({
			'over': this.dragEnter.bind(el),
			'leave': this.dragLeave.bind(el),
			'drop': this.drop.bind(el)
		});
		
		
		return el;
	},
	

	createContentArea: function () {
		this.contentArea = this.contentArea || new URSPIN.ColumnedContentArea(this.options).injectInside($('content-bodies'));	
		return this.contentArea;
	},

	dragEnter: function (dropEl, drag) {
		// console.log('enter', this, arguments);

		this.addClass('tab-hover');
		if ($defined(dropEl.wirePreview.getParent())) {
			dropEl.wirePreview.remove();
		}
	},

	// dragOver: function (dropEl, drag) {
	// },
	
	dragLeave: function (dropEl, drag) {
		// console.log('leave', this, arguments);
		this.removeClass('tab-hover');
		dropEl.wirePreview.injectAfter(dropEl);
	},

	drop: function (dropEl, drag) {
		// console.log('drop', this, arguments);

		this.removeClass('tab-hover');

		dropEl.options.column = null;
		dropEl.options.row = null;

		this.moveModule(dropEl, 0, 0);

	},

	moveModule: function (module, column, columnInnerPosition, options) {
		// console.log('tab: moveModule %o (%d, %d)', module, column, columnInnerPosition);
		options = options || {};
		options.move = true;
		this.addModule(module, column, columnInnerPosition, options);
	},

	
	addModule: function (module, i, j, options) {
		// console.log('ModuleTab.addModule', arguments);
		options = options || {};

		if (options.move) {
			this.getContentArea(true).moveModule(module, i, j);
		} else {
			this.getContentArea(true).addModule(module, i, j);
		}
		if (options.switchToTab) {
			URSPIN.getWebtop().getTabManager().openTab(this);
		}
	},
	
	addNewModule: function (m, c, cip, o) {
		return this.moveModule(m, c, cip, o);
	}


});


/*
	Class: URSPIN.TabManager
*/
URSPIN.TabManager = new Class({

	options: {
		'hasAddTabButton': false,
		'openedUserTabID': null,
		'taborder': ''
	},
	
	tabs: null,
	tabBarMarker: null,
	
	currentlyOpenedTab: null,
	
	$URSPIN_isTabManager:true,
	
	initialize: function (tabDataRaw, options) {
		this.setOptions(options);

		var tabBar = $('tab-bar');

		this.tabs = [];
		var t = tabBar.getElement('#tabs');
		this.tabBarMarker = t.getElement('.cb');

		$extend(tabBar, this);

		if (this.options.hasAddTabButton) {
			// create "add tab" button
			var a = URSPIN.Webtop.buildButton({
				'id':'tab-bar-add-tab',
				'text':URSPIN.l10n.getString('ui.tabbar.addtab'),
				'onClick':this.addNewTab.bindWithEvent(tabBar),
				'iconSrc':'btn_icn_plus'
			});
			$('tab-add-btn-wrap').adopt(a);
			// a.injectAfter(t);
		}


		var order = this.options.taborder.split(',');
		if (order[order.length - 1].trim() == '') {
			order.pop();
		}
		// add tabs by order 
		// each added tab is removed from raw array
		for (var j = 0; j < order.length; j++) {
			for (var i = 0; i < tabDataRaw.length; i++) {
				if (tabDataRaw[i][0] == order[j]) {
					var tabData = {
						'userTabID': tabDataRaw[i][0],
						'tabTypeID': tabDataRaw[i][1],
						'title': tabDataRaw[i][2],
						'iconImgSrc': tabDataRaw[i][3],
						'removable': tabDataRaw[i][4],
						'renamable': tabDataRaw[i][5],
						'sharable': tabDataRaw[i][6],
						'customizable': tabDataRaw[i][7],
						'colWidthStyle': tabDataRaw[i][8]
					};

					tabBar.addTabByData.call(tabBar, tabData);
					tabDataRaw.splice(i, 1);
					break;
				}
			}
		}
		// if there is any more data in the raw array
		// then we add the rest tabs
		if (tabDataRaw.length > 0) {
			for (var i = 0; i < tabDataRaw.length; i++) {
				var tabData = {
					'userTabID': tabDataRaw[i][0],
					'tabTypeID': tabDataRaw[i][1],
					'title': tabDataRaw[i][2],
					'iconImgSrc': tabDataRaw[i][3],
					'removable': tabDataRaw[i][4],
					'renamable': tabDataRaw[i][5],
					'sharable': tabDataRaw[i][6],
					'customizable': tabDataRaw[i][7],
					'colWidthStyle': tabDataRaw[i][8]
				};
		
				tabBar.addTabByData.call(tabBar, tabData);
				// tabDataRaw.splice(i, 1);
			}
		}
		
		var tab = this.getTabByID.call(tabBar, this.options.openedUserTabID)  || tabBar.tabs[0];
		tabBar.openTab.call(tabBar, tab, true);
		

		tabBar.scrollPos = 0;
		var d = 71;
		var tabsEl = $('tabs');
		tabsEl.scrollEffect = tabsEl.effect('left', {duration:150,wait:false});
		
		$('tabs-scroll-left').addEvent('click', function () {
			if (tabBar.scrollPos < 0) {
				tabBar.scrollPos += d;
				tabsEl.scrollEffect.start(tabBar.scrollPos);
				$('tabs-scroll-right').addClass('active');
			}
			if (tabBar.scrollPos == 0) {
				$('tabs-scroll-left').removeClass('active');
			}
		});
		$('tabs-scroll-right').addEvent('click', function () {
			// check boundry
			tabBar.scrollPos -= d;
			tabsEl.scrollEffect.start(tabBar.scrollPos);
			$('tabs-scroll-left').addClass('active');
		});
		
		window.addEvent('resize', this.resize.bind(tabBar));
		
		
		return tabBar;
	},
	

	resize: function () {
		var t = $('tabs');
		t.setStyle('width', this.tabs.length * 71);

		if (t.offsetWidth > this.offsetWidth) {
			this.addClass('needs-scroll');
			$('tabs-scroll-right').addClass('active');
		} else {
			this.removeClass('needs-scroll');
			t.setStyle('left', 0);
			$('tabs-scroll-left').removeClass('active');
			$('tabs-scroll-right').removeClass('active');
		}

	},
	
	addTabByData: function (tabData, options) {return this.addTab(URSPIN.TabFactory.newTab(tabData), options);},

	addTab: function (tab, options) {
		options = options || {};

		// console.log('addTab', this.tabs.length);
		
		this.tabs.push(tab);
		tab.removeEvents('mousedown');
		tab.addEvent('mousedown', function (e) {this.openTab(tab, null, e);}.bindWithEvent(this));

		this.resize();

		tab.injectBefore(this.tabBarMarker);

		tab.close();

		if (options.openTab) {
			this.openTab(tab);
		}

		return tab;
	},

	addNewTab: function (e, tabOptions, onSuccess) {
		tab = this.addTab(URSPIN.TabFactory.newTab(tabOptions));
		
		var uri = 'services/wt/user/';
		var data = $merge(tab.options, {
			'cmd':'newTab'
		});

		var xhr = new XHR({'onSuccess':function (text, xml) {
			var data = Json.evaluate(text);
			tab.setUserTabID(data.newTab);
			tab.contentArea.isContentLoaded = true;
			if (onSuccess) {
				console.log('onSuccess', this, this.onSuccess);
				onSuccess.call(this);
			}
		}.bind(tab)});

		xhr.send(uri, Object.toQueryString(data));
		
		this.openTab(tab);
		return tab;
	},


	removeTab: function (tab) {
		var i = this.tabs.indexOf(tab);
		if (i >= 0) {
			// console.log('removeTab', i);
			// remove from manager's array
			this.tabs.splice(i, 1);
			
			// remove tab and related from DOM
			tab.removeSelfAndRelated();
			this.currentlyOpenedTab = null;

			this.resize();

			if (tab.options.userTabID && ($type(tab.options.userTabID) == 'number' ||  tab.options.userTabID.test('[0-9]+'))) {
				// keep reference for undo
				this.lastRemovedTab = tab;


				var uri = 'services/wt/user/';
				var data = {
					'cmd':'rmTab',
					'uTID':tab.options.userTabID
				};

				var xhr = new XHR();

				xhr.send(uri, Object.toQueryString(data));
				URSPIN.Notify.undo([URSPIN.l10n.getString('ui.notify.tab.removeprepend'), '"',  tab.displayTitle, '"', URSPIN.l10n.getString('ui.notify.tab.removeappend')].join(''), this.undoLastRemove.bind(this));
			}
			tab.removeEvents('mousedown');

			this.openTabByIndex.delay(0, this, [i,{'orNearby':true}]);

			return tab;

		}
	},
	
	undoLastRemove: function () {
		if (this.lastRemovedTab) {
			var tab = this.lastRemovedTab;
			this.lastRemovedTab = null;

			this.addTab(tab);

			if (tab.options.userTabID && ($type(tab.options.userTabID) == 'number' ||  tab.options.userTabID.test('[0-9]+'))) {

				var uri = 'services/wt/user/';
				var data = {
					'cmd':'urmTab',
					'uTID':tab.options.userTabID
				};

				var xhr = new XHR();
				xhr.send(uri, Object.toQueryString(data));


			}




			this.openTab.delay(0, this, [tab]);


		}
	},



	getTabByID: function (userTabID) {
		for (var i = 0; i < this.tabs.length; i++) {
			if (this.tabs[i].getID() == userTabID) {
				return this.tabs[i];
			}
		}
		return null;
	},
	
	updateTabOrder: function (openedTab) {
		var s = [];
		$('tabs').getElements('.tab').each(function (t) {
			s.push(t.options.userTabID);
		});
		var order = s.join('-');
		var data = {'cmd':'updateTabOrder','order':order};
		if (($type(openedTab.options.userTabID) != 'string' || !openedTab.options.userTabID.test("^n\-"))) {
			data.opened = openedTab.getID();
		}
		new XHR({}).send('services/wt/user/',Object.toQueryString(data));
	},

	openTab: function (selectedTab, dontRecord, e) {
		// console.log('openTab');
		if (this.currentlyOpenedTab != selectedTab) {
			var previousTab = this.currentlyOpenedTab;
			if (previousTab) {
				previousTab.removeEvents('mousedown');
				previousTab.addEvent('mousedown', function (e) {this.openTab(previousTab, null, e);}.bindWithEvent(this));
				previousTab.close();
				
			}
			var tabMan = this;
			
			var startDrag = function (e) {
				// console.log('tab: startDrag', arguments);
				var tabsEl = $('tabs');
				var tabs = tabsEl.getElements('.tab');

				this.isSnapped = false;
				this.snapX = e.page.x;
				
				this.onMouseMove = function (e) {
					// console.log('tab: onMouseMove', arguments);
					if (this.isSnapped) {
						this.setStyles({'left':e.page.x - (this.offsetWidth / 2)});
						if (e.page.x > tabsEl.offsetWidth) {
							this.wire.injectBefore(tabsEl.getElement('.cb'));
						} else if (e.page.x <= 0){
							this.wire.injectTop(tabsEl);
						} else {
							for (var i = 0; i < tabs.length; i++) {
								var tab = tabs[i];
								if (tab != this) {
									var c = tab.getCoordinates();
									if (e.page.x >= c.left && e.page.x <= c.left  + (c.width / 2)) {
										this.wire.injectBefore(tab);
										break;
									} else if (e.page.x >= c.left  + (c.width / 2) && e.page.x <= c.right) {
										this.wire.injectAfter(tab);
										break;
									}
								}

							}
						}
					} else {
						if (Math.abs(e.page.x - this.snapX) > 20) {
							// console.log('tab: snapped');
							this.addClass('tab-drag');
							this.isSnapped = true;

							this.wire = new Element('div',{'class':'tab-wire'});
							
							var l = this.getCoordinates().left;
							
							this.replaceWith(this.wire);
							this.setStyles({
								'position':'absolute',
								'left':l
							});
							this.injectBefore($('tabs').getElement('.cb'));
						}
					}
				}.bindWithEvent(this);


				this.onMouseUp = function (e) {
					// console.log('tab: onMouseUp', arguments);
					document.removeListener('mousemove', this.onMouseMove);
					document.removeListener('mouseup', this.onMouseUp);

					if (this.isSnapped) {
						this.removeClass('tab-drag');
						e.stop();

						this.remove();
						this.setStyles({'position':'','left':''});
						this.wire.replaceWith(this);

					}

					this.open(dontRecord);
					tabMan.currentlyOpenedTab = selectedTab;
					tabMan.updateTabOrder(this);

				}.bindWithEvent(this);

				document.addListener('mousemove', this.onMouseMove);
				document.addListener('mouseup', this.onMouseUp);

			};
			
			selectedTab.removeEvents('mousedown');
			selectedTab.addEvent('mousedown', startDrag.bindWithEvent(selectedTab));

			if ($defined(e)) {
				startDrag.call(selectedTab, e);
			} else {
				if (!dontRecord) {
					this.updateTabOrder(selectedTab);
				}
				selectedTab.open(dontRecord);
				this.currentlyOpenedTab = selectedTab;
			}


		}
		
		return this.currentlyOpenedTab;
	},

	openTabByIndex: function (i, options) {
		options = options || {};
		if ($defined(this.tabs[i])) {
			return this.openTab(this.tabs[i]);
		} else if (options.orNearby) {
			if ($defined(this.tabs[i - 1])) {
				return this.openTab(this.tabs[i - 1]);
			} else if ($defined(this.tabs[i + 1])) {
				return this.openTab(this.tabs[i + 1]);
			}
		}
		
		return null;
	},

	
	openNextTab: function () {
		var i = this.tabs.indexOf(this.currentlyOpenedTab);
		if ($defined(this.tabs[i + 1])) {
			return this.openTab(this.tabs[i + 1]);
		} else {
			return this.openTab(this.tabs[0]);
		}
	},

	openPrevTab: function () {
		var i = this.tabs.indexOf(this.currentlyOpenedTab);
		if ($defined(this.tabs[i - 1])) {
			return this.openTab(this.tabs[i - 1]);
		} else {
			return this.openTab(this.tabs[this.tabs.length - 1]);
		}
	},

	addNewModule: function (module) {
		if ($type(this.currentlyOpenedTab.addNewModule) == 'function') {
			this.currentlyOpenedTab.addNewModule(module);
		} else {
			// TODO
		}
		
	},
	
	getTabs: function () {
		return this.tabs;
	},
	
	getCurrentTab: function () {
		return this.currentlyOpenedTab;
	},
	
	getTabsThatCanAddModules: function () {
		return this.tabs.filter(function (tab, i) {
			return $type(tab.addModule) == 'function';
		});
	}

});
URSPIN.TabManager.implement(new Options, new Events);