Ext.ns('Nexts.plugins');

/**
 * @class Nexts.plugins.IconMenu
 * @extends Ext.util.Observable
 *
 * @constructor
 * Creates new IconMenu
 * @param {Object} config The configuration object
 */
Nexts.plugins.IconMenu = function(config) {
	// apply config
	Ext.apply(this, config);

	// call parent
	Nexts.plugins.IconMenu.superclass.constructor.apply(this, arguments);

};

Ext.extend(Nexts.plugins.IconMenu, Ext.util.Observable, {

	// configuration options

	/**
	 * @cfg {String} iconCls Optional. If the iconCls of Panel/Window is not set, then used this
	 */
	iconCls: 'ne-iconmenu-panel-icon-default',

	/**
	 * @cfg {String} maximizeText Text for Maximize item
	 */
	maximizeText:'Maximize',
	
	/**
	 * @cfg {String} minimizeText Text for Minimize item
	 */
	minimizeText:'Minimize',

	/**
	 * @cfg {String} restoreText Text for Restor item
	 */
	restoreText:'Restore',

	/**
	 * @cfg {String} closeText Text for Close item
	 */
	 closeText:'Close',

	/**
	 * @cfg {Boolean} createDefault false to not create default menu
	 */
	createDefault:true,

	/**
	 * @cfg {Boolean} dblClickClose false to disable dblclick close action (defaults to true)
	 */
	dblClickClose:true,

	/**
	 * @cfg {Array} customItems Array of menu items configs.
	 * For example:
	 * new Nexts.plugins.IconMenu:({
	 *  customItems:['separator'
	 *	,{
	 *		 text:'This is <b>zoom</b> item'
	 *		,iconCls:'icon-zoom'
	 *		,handler: function() {console.info(arguments)}
	 *	},{
	 *		 text:'This is <b>print</b> item'
	 *		,iconCls:'icon-print'
	 *		,handler: function() {console.info(arguments)}
	 *	}]
	 */

	/**
	 * @cfg {Array} defaultItems Default items to create. If you add items you need to add texts and handlers too.
	 */
	defaultItems:['restore', 'minimize', 'maximize', 'separator', 'close'],

	// methods

	/** 
	 * Closes Panel/Window
	 * @private
	 */
	closeHandler: function() {
		if (this.panel.closable) {
			this.panel[this.panel.closeAction]();
		}
	},

	/**
	 * Maximizes Panel/Window
	 * @private
	 */
	maximizeHandler: function() {
		this.hideMenu();
		if (this.panel.maximizable) {
			this.panel.maximize();
		}
	},

	/**
	 * Minimizes Panel/Window
	 * @private
	 */
	minimizeHandler: function() {
		this.hideMenu();
		if (this.panel.minimizable) {
			this.panel.minimize();
		}
	},

	/**
	 * Restores Panel/Window
	 * @private
	 */
	restoreHandler: function() {
		this.hideMenu();
		this.panel.restore();
	},

	/**
	 * Returns menu item identified by cmd
	 * @param {String} cmd 
	 * @return {Ext.menu.Item}
	 */
	getItemByCmd: function(cmd) {
		if (!this.menu || !cmd) {
			return null;
		}
		var item = this.menu.items.find(function(i) {
			return cmd === i.cmd;
		});
		return item;
	},

	/**
	 * Hides menu
	 */
	hideMenu: function() {
		if (this.menu) {
			this.menu.hide();
		}
	},

	/**
	 * Main init function
	 * @private
	 * @param {Ext.Panel/Ext.Window} panel Panel/Window this plugin is in
	 */
	init: function(panel) {
		this.panel = panel;
		if (!panel.iconCls) {
			panel.iconCls = this.iconCls;
		}

		panel.on({
			hide: this.hideMenu,
			destroy: this.onDestroy,
			scope: this
		});

		// override panel's setIconClass method
		this.panel.setIconClass = this.setIconClass.createDelegate(this);

		// create default menu
		var i, cfg, item;
		var menuId = 'im-' + panel.id;

		// create default menu
		if (this.createDefault && Ext.isArray(this.defaultItems) && this.defaultItems.length) {
			if (this.menu) {
				this.menu.add('-');
			}
			else {
				this.menu = new Ext.menu.Menu({id:menuId});
			}
			for (i = 0; i < this.defaultItems.length; i++) {
				this.addItem(this.defaultItems[i]);
			}
		}

		// create custom menu
		if (Ext.isArray(this.customItems)) {
			if (!this.menu) {
				this.menu = new Ext.menu.Menu({id:menuId});
			}
			for (i = 0; i < this.customItems.length; i++) {
				this.addItem(this.customItems[i]);
			}
		}

		// install handlers
		if (this.menu) {
			this.menu.on({
				"beforeshow": this.beforeMenuShow,
				"scope": this
			});
		}
	},

	/**
	 * Adds item to menu
	 * @private
	 * @param {String/Object} item String for default items config object for custom items
	 */
	addItem: function(item) {
		if ('separator' === item || '-' === item) {
			this.menu.add('-');
			return;
		}
		var cfg;
		if ('string' === typeof item) {
			cfg = {
				text: this[item + 'Text'],
				cmd: item,
				iconCls: 'ne-iconmenu-menu-icon x-tool x-tool-' + item,
				handler:this[item + 'Handler'],
				scope: this
			};
		}
		else {
			cfg = item;
		}
		this.menu.add(cfg);
	},

	/**
	 * Destroys underlying menu
	 * @private
	 */
	onDestroy: function() {
		if (this.menu) {
			Ext.destroy(this.menu);
			delete this.menu;
		}
	},

	/**
	 * Replaces Panel/Window setIconClass method
	 * @private
	 */
	setIconClass: function(iconCls) {
		var oldIconCls = this.panel.iconCls;
		
		if (this.icon) {
			this.icon.replaceClass(oldIconCls, this.panel.iconCls);
		}
		else {
			if (this.panel.rendered && this.panel.header) {
				if (this.panel.header.hasClass('x-panel-icon')) {
					this.panel.header.removeClass('x-panel-icon');
					this.panel.header.removeClass(this.panel.iconCls);
				}

				var hd = this.panel.header.dom;
				var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;

				if (img) {
					this.icon = Ext.get(img);
					this.icon.addClass('ne-iconmenu-panel-icon');
				}
				else {
					// create icon
					this.icon = Ext.DomHelper.insertBefore(hd.firstChild, {
						tag: 'img', 
						src: Ext.BLANK_IMAGE_URL, 
						cls: 'x-panel-inline-icon r-iconmenu-panel-icon ' + this.panel.iconCls
					}, true);
				}

				// install icon event handlers
				this.icon.on({
					dblclick: {
						fn : function(e) {
							if (this.dblClickClose) {
								e.stopPropagation();
								this.closeHandler.defer(100, this);
							}
						},
						scope: this
					},
					click: {
						fn: function() {
							if (this.menu && !this.menu.isVisible()) {
								this.menu.show(this.icon, 'tl-bl?');
							}
						},
						scope: this
					}
				});
			}
		}
	},

	/**
	 * beforeMenuShow
	 */
	beforeMenuShow: function() {
		var item;

		// enable/disable close
		item = this.getItemByCmd('close');
		if (item) {
			item.setDisabled(!this.panel.closable);
		}

		// enable/disable maximize
		item = this.getItemByCmd('maximize');
		if (item) {
			item.setDisabled(!this.panel.maximizable || this.panel.maximized);
		}

		// enable/disable minimize
		item = this.getItemByCmd('minimize');
		if (item) {
			item.setDisabled(!this.panel.minimizable || this.panel.minimized);
		}

		// enable/disable restore
		item = this.getItemByCmd('restore');
		if (item) {
			item.setDisabled(!(this.panel.minimized || this.panel.maximized));
		}
	}
}); 

