Ext.ns('Nexts.desktop');

/**
 * @class Nexts.desktop.TaskBar
 * @extends Ext.util.Observable
 */
Nexts.desktop.TaskBar = function(config) {
	Ext.apply(this, config);
	
	this.init();

	Nexts.desktop.TaskBar.superclass.constructor.call(this);
}

Ext.extend(Nexts.desktop.TaskBar, Ext.util.Observable, {
	startText: 'Start',
	
	init: function() {
		this.startMenu = new Nexts.desktop.StartMenu(this.startConfig);
		
		this.startButton = new Ext.Button({
			text: this.startText,
			id: 'ne-startbutton',
			iconCls: 'ne-start',
			menu: this.startMenu,
			menuAlign: 'bl-tl',
			renderTo: 'ne-taskbar-start'
		});
		
		var startWidth = Ext.get('ne-startbutton').getWidth() + 10;
		
		var sbBox = new Ext.BoxComponent({
			el: 'ne-taskbar-start',
			id: 'TaskBarStart',
			minWidth: startWidth,
			region:'west',
			split: false,
			width: startWidth
		});
		
		this.quickStart = new Nexts.desktop.QuickStart({
			el: 'ne-quickstart',
			id: 'TaskBarQuickStart',
			minWidth: 60,
			region:'west',
			split: true,
			width: 94
		});
		
		this.taskButtons = new Nexts.desktop.TaskBar.TaskButtons({
			el: 'ne-taskbuttons',
			id: 'TaskBarButtons',
			region:'center'
		});
		
		var panelWrap = new Ext.Container({
			el: 'ne-taskbar-panel-wrap',
			items: [this.quickStart,this.taskButtons],
			layout: 'border',
			region: 'center'
		});
				
		var container = new Nexts.desktop.TaskBar.Container({
			el: 'ne-taskbar',
			layout: 'border',
			items: [sbBox,panelWrap]
		});
		this.el = container.el;
		
		return this;
	},
	
	setActiveButton: function(btn) {
		this.taskButtons.setActiveButton(btn);
	}
});


/**
 * @class Nexts.desktop.TaskBar.Container
 * @extends Ext.Container
 */
Nexts.desktop.TaskBar.Container = Ext.extend(Ext.Container, {
	initComponent: function() {
		Nexts.desktop.TaskBar.Container.superclass.initComponent.call(this);
		
		this.el = Ext.get(this.el) || Ext.getBody();
		this.el.setHeight = Ext.emptyFn;
		this.el.setWidth = Ext.emptyFn;
		this.el.setSize = Ext.emptyFn;
		this.el.setStyle({
			overflow:'hidden',
			margin:'0',
			border:'0 none'
		});
		this.el.dom.scroll = 'no';
		this.allowDomMove = false;
		this.autoWidth = true;
		this.autoHeight = true;
		Ext.EventManager.onWindowResize(this.fireResize, this);
		this.renderTo = this.el;
	},

	fireResize: function(w, h) {
		this.fireEvent('resize', this, w, h, w, h);
	}
});

/**
 * @class Nexts.desktop.TaskBar.TaskButton
 * @extends Ext.Button
 */
Nexts.desktop.TaskBar.TaskButton = function(win, el) {
	this.win = win;
	
	Nexts.desktop.TaskBar.TaskButton.superclass.constructor.call(this, {
		iconCls: win.iconCls,
		text: String.ellipsiz(win.title, 12),
		tooltip: win.taskbuttonTooltip || win.title,
		renderTo: el,
		handler: function() {
			var w = this.win;
			if (w.minimized || w.hidden) {
				w.show();
			}
			else if (w == w.manager.getActive()) {
				w.minimize();
			}
			else {
				w.toFront();
			}
		},
		scope: this,
		clickEvent:'mousedown'
	});
};

Ext.extend(Nexts.desktop.TaskBar.TaskButton, Ext.Button, {
	restoreText: 'Restore',
	minimizeText: 'Minimize',
	maximizeText: 'Maximize',
	closeText: 'Close',
	
	restoreWindow: function() {
		if (!this.win.isVisible()) {
			this.win.show();
		}
		else {
			this.win.restore();
		}
	},
	
	minimizeWindow: function() {
		if (!this.win.minimized) {
			this.win.minimize();
		}
	},
	
	maximizeWindow: function() {
		if (this.win.maximizable && !this.win.maximized) {
			this.win.maximize();
		}
		if (!this.win.isVisible()) {
			this.win.show();
		}
	},
	
	closeWindow: function() {
		this.win.close();
	},
	
	beforeDestroy: function() {
		Nexts.desktop.TaskBar.TaskButton.superclass.beforeDestroy.apply(this, arguments);
		if (this.cmenu) {
			Ext.destroy(this.cmenu);
			delete this.cmenu;
		}
	},

	onRender: function() {
		Nexts.desktop.TaskBar.TaskButton.superclass.onRender.apply(this, arguments);

		this.cmenu = new Ext.menu.Menu({
			items: [{
				id: 'restore',
				text: this.restoreText,
				iconCls: 'ne-taskbutton-menu-icon x-tool x-tool-restore',
				handler: this.restoreWindow,
				scope: this
			},{
				id: 'minimize',
				text: this.minimizeText,
				iconCls: 'ne-taskbutton-menu-icon x-tool x-tool-minimize',
				handler: this.minimizeWindow,
				scope: this
			},{
				id: 'maximize',
				text: this.maximizeText,
				iconCls: 'ne-taskbutton-menu-icon x-tool x-tool-maximize',
				handler: this.maximizeWindow,
				scope: this
			}, '-', {
				id: 'close',
				text: this.closeText,
				iconCls: 'ne-taskbutton-menu-icon x-tool x-tool-close',
				handler: this.closeWindow,
				scope: this
			}]
		});

		this.cmenu.on('beforeshow', function() {
			var items = this.cmenu.items.items;
			var w = this.win;
			items[0].setDisabled(w.maximized !== true && w.hidden !== true);
			items[1].setDisabled(w.minimized === true);
			items[2].setDisabled(w.maximized === true || w.hidden === true);
			items[2].setDisabled(w.maximizable === false);
			items[3].setDisabled(w.closable === false);
		}, this);

		this.el.on('contextmenu', function(e) {
			e.stopEvent();
			if (!this.cmenu.el) {
				this.cmenu.render();
			}
			var xy = e.getXY();
			xy[1] -= this.cmenu.el.getHeight();
			this.cmenu.showAt(xy);
		}, this);
	},
	
	/**
	 * override so autoWidth() is not called
	 * @param {String} text The text for the button
	 */
	setText: function(text) {
		if (text) {
			this.text = text;
			if (this.el) {
				this.el.child("td.x-btn-center " + this.buttonSelector).update(String.ellipsiz(text, 12));
			}
		}
	},
	
	/**
	 * @param {String/Object} tooltip The tooltip for the button - can be a string or QuickTips config object
	 */
	setTooltip: function(text) {
		if (text) {
			this.tooltip = text;
			var btnEl = this.el.child(this.buttonSelector);
			Ext.QuickTips.unregister(btnEl.id);
			
			if (typeof this.tooltip == 'object') {				
				Ext.QuickTips.register(Ext.apply({
					  target: btnEl.id
				}, this.tooltip));
			} else {
				btnEl.dom[this.tooltipType] = this.tooltip;
			}
		}
	}
});

/**
 * @class Nexts.desktop.TaskBar.TaskButtons
 * @extends Ext.BoxComponent
 */
Nexts.desktop.TaskBar.TaskButtons = Ext.extend(Ext.BoxComponent, {
	activeButton: null,
	enableScroll: true,
	scrollIncrement: 0,
	scrollRepeatInterval: 400,
	scrollDuration: .35,
	animScroll: true,
	resizeButtons: true,
	buttonWidth: 168,
	minButtonWidth: 118,
	buttonMargin: 2,
	buttonWidthSet: false,
	
	maximizeAllText: 'Maximize all windows',
	minimizeAllText: 'Minimize all windows',
	restoreAllText: 'Restore all windows',
	closeAllText: 'Close all windows',
	
	closeAllHandler: function() {
		if (this.items.length > 0) {
			var i = this.items[0];
			i.closeWindow();
			if (!this.items.contains(i)) {
				this.closeAllHandler();
			}
		}
	},
	
	onRender: function() {
		Nexts.desktop.TaskBar.TaskButtons.superclass.onRender.apply(this, arguments);
		
		this.cmenu = new Ext.menu.Menu({
			items: [{
				id: 'restoreAll',
				text: this.restoreAllText,
				iconCls: 'ne-xtool-menu-icon x-tool x-tool-restore',
				handler: function() {
					this.items.each(function(it) {
						it.restoreWindow();
					});
				},
				scope: this
			},{
				id: 'minimizeAll',
				text: this.minimizeAllText,
				iconCls: 'ne-xtool-menu-icon x-tool x-tool-minimize',
				handler: function() {
					this.items.each(function(it) {
						it.minimizeWindow();
					});
				},
				scope: this
			},{
				id: 'maximizeAll',
				text: this.maximizeAllText,
				iconCls: 'ne-xtool-menu-icon x-tool x-tool-maximize',
				handler: function() {
					this.items.each(function(it) {
						it.maximizeWindow();
					});
				},
				scope: this
			}, '-', {
				id: 'closeAll',
				text: this.closeAllText,
				iconCls: 'ne-xtool-menu-icon x-tool x-tool-close',
				handler: this.closeAllHandler,
				scope: this
			}]
		});

		this.cmenu.on('beforeshow', function() {
		}, this);

		this.el.on('contextmenu', function(e) {
			e.stopEvent();
			this.cmenu.showAt(e.getPoint());
		}, this);
	},
	
	initComponent: function() {
		Nexts.desktop.TaskBar.TaskButtons.superclass.initComponent.call(this);
		this.on('resize', this.delegateUpdates);
		this.items = [];
		
		this.stripWrap = Ext.get(this.el).createChild({
			cls: 'ne-taskbuttons-strip-wrap',
			cn: {
				tag:'ul', cls:'ne-taskbuttons-strip'
			}
		});
		this.stripSpacer = Ext.get(this.el).createChild({
			cls:'ne-taskbuttons-strip-spacer'
		});
		this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
		
		this.edge = this.strip.createChild({
			tag:'li',
			cls:'ne-taskbuttons-edge'
		});
		this.strip.createChild({
			cls:'x-clear'
		});
	},
	
	add: function(win) {
		var li = this.strip.createChild({tag:'li'}, this.edge); // insert before the edge
		var btn = new Nexts.desktop.TaskBar.TaskButton(win, li);
		
		this.items.push(btn);
		
		if (!this.buttonWidthSet) {
			this.lastButtonWidth = btn.container.getWidth();
		}
		
		this.setActiveButton(btn);
		return btn;
	},
	
	remove: function(btn) {
		var li = document.getElementById(btn.container.id);
		btn.destroy();
		li.parentNode.removeChild(li);
		
		this.items.remove(btn);
		
		this.delegateUpdates();
	},
	
	setActiveButton: function(btn) {
		this.activeButton = btn;
		this.delegateUpdates();
	},
	
	delegateUpdates: function() {
		/*if (this.suspendUpdates) {
			return;
		}*/
		if (this.resizeButtons && this.rendered) {
			this.autoSize();
		}
		if (this.enableScroll && this.rendered) {
			this.autoScroll();
		}
	},
	
	autoSize: function() {
		var count = this.items.length;
		var ow = this.el.dom.offsetWidth;
		var aw = this.el.dom.clientWidth;

		if (!this.resizeButtons || count < 1 || !aw) { // !aw for display:none
			return;
		}
		
		var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.buttonMargin, this.buttonWidth), this.minButtonWidth); // -4 for float errors in IE
		var btns = this.stripWrap.dom.getElementsByTagName('button');
		
		this.lastButtonWidth = Ext.get(btns[0].id).findParent('li').offsetWidth;
		
		for(var i = 0, len = btns.length; i < len; i++) {			 
			var btn = btns[i];
			
			var tw = Ext.get(btns[i].id).findParent('li').offsetWidth;
			var iw = btn.offsetWidth;
			
			btn.style.width = (each - (tw-iw)) + 'px';
		}
	},
	
	autoScroll: function() {
		var count = this.items.length;
		var ow = this.el.dom.offsetWidth;
		var tw = this.el.dom.clientWidth;
		
		var wrap = this.stripWrap;
		var cw = wrap.dom.offsetWidth;
		var pos = this.getScrollPos();
		var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
		
		if (!this.enableScroll || count < 1 || cw < 20) { // 20 to prevent display:none issues
			return;
		}
		
		wrap.setWidth(tw); // moved to here because of problem in Safari
		
		if (l <= tw) {
			wrap.dom.scrollLeft = 0;
			//wrap.setWidth(tw); moved from here because of problem in Safari
			if (this.scrolling) {
				this.scrolling = false;
				this.el.removeClass('ne-taskbuttons-scrolling');
				this.scrollLeft.hide();
				this.scrollRight.hide();
			}
		}else{
			if (!this.scrolling) {
				this.el.addClass('ne-taskbuttons-scrolling');
			}
			tw -= wrap.getMargins('lr');
			wrap.setWidth(tw > 20 ? tw: 20);
			if (!this.scrolling) {
				if (!this.scrollLeft) {
					this.createScrollers();
				}else{
					this.scrollLeft.show();
					this.scrollRight.show();
				}
			}
			this.scrolling = true;
			if (pos > (l-tw)) { // ensure it stays within bounds
				wrap.dom.scrollLeft = l-tw;
			}else{ // otherwise, make sure the active button is still visible
				this.scrollToButton(this.activeButton, true); // true to animate
			}
			this.updateScrollButtons();
		}
	},

	createScrollers: function() {
		var h = this.el.dom.offsetHeight; //var h = this.stripWrap.dom.offsetHeight;
		
		// left
		var sl = this.el.insertFirst({
			cls:'ne-taskbuttons-scroller-left'
		});
		sl.setHeight(h);
		sl.addClassOnOver('ne-taskbuttons-scroller-left-over');
		this.leftRepeater = new Ext.util.ClickRepeater(sl, {
			interval: this.scrollRepeatInterval,
			handler: this.onScrollLeft,
			scope: this
		});
		this.scrollLeft = sl;

		// right
		var sr = this.el.insertFirst({
			cls:'ne-taskbuttons-scroller-right'
		});
		sr.setHeight(h);
		sr.addClassOnOver('ne-taskbuttons-scroller-right-over');
		this.rightRepeater = new Ext.util.ClickRepeater(sr, {
			interval: this.scrollRepeatInterval,
			handler: this.onScrollRight,
			scope: this
		});
		this.scrollRight = sr;
	},
	
	getScrollWidth: function() {
		return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
	},

	getScrollPos: function() {
		return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
	},

	getScrollArea: function() {
		return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
	},

	getScrollAnim: function() {
		return {
			duration: this.scrollDuration,
			callback: this.updateScrollButtons,
			scope: this
		};
	},

	getScrollIncrement: function() {
		return (this.scrollIncrement || this.lastButtonWidth+2);
	},
	
	/* getBtnEl: function(item) {
		return document.getElementById(item.id);
	}, */
	
	scrollToButton: function(item, animate) {
		item = item.el.dom.parentNode; // li
		if (!item) { return; }
		var el = item; //this.getBtnEl(item);
		var pos = this.getScrollPos(), area = this.getScrollArea();
		var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
		var right = left + el.offsetWidth;
		if (left < pos) {
			this.scrollTo(left, animate);
		}else if (right > (pos + area)) {
			this.scrollTo(right - area, animate);
		}
	},
	
	scrollTo: function(pos, animate) {
		this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim(): false);
		if (!animate) {
			this.updateScrollButtons();
		}
	},
	
	onScrollRight: function() {
		var sw = this.getScrollWidth()-this.getScrollArea();
		var pos = this.getScrollPos();
		var s = Math.min(sw, pos + this.getScrollIncrement());
		if (s != pos) {
			this.scrollTo(s, this.animScroll);
		}		 
	},

	onScrollLeft: function() {
		var pos = this.getScrollPos();
		var s = Math.max(0, pos - this.getScrollIncrement());
		if (s != pos) {
			this.scrollTo(s, this.animScroll);
		}
	},
	
	updateScrollButtons: function() {
		var pos = this.getScrollPos();
		this.scrollLeft[pos == 0 ? 'addClass': 'removeClass']('ne-taskbuttons-scroller-left-disabled');
		this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('ne-taskbuttons-scroller-right-disabled');
	}
});


