/**
 * MenuButton.js
 *
 * Copyright 2003-2012, Moxiecode Systems AB, All rights reserved.
 */

/**
 * ..
 *
 * @-x-less MenuButton.less
 * @class tinymce.ui.MenuButton
 * @extends tinymce.ui.Button
 */
define("tinymce/ui/MenuButton", [
	"tinymce/ui/Button",
	"tinymce/ui/Factory",
	"tinymce/ui/MenuBar"
], function(Button, Factory, MenuBar) {
	"use strict";

	// TODO: Maybe add as some global function
	function isChildOf(node, parent) {
		while (node) {
			if (parent === node) {
				return true;
			}

			node = node.parentNode;
		}

		return false;
	}

	var MenuButton = Button.extend({
		init: function(settings) {
			var self = this;

			self._renderOpen = true;
			self._super(settings);

			self.addClass('menubtn');

			self.aria('haspopup', true);
			self.hasPopup = true;
		},

		showMenu: function() {
			var self = this, settings = self.settings, menu;

			if (!self.menu) {
				menu = settings.menu || [];

				// Is menu array then auto constuct menu control
				if (menu.length) {
					menu = {
						type: 'menu',
						items: menu
					};
				} else {
					menu.type = menu.type || 'menu';
				}

				self.menu = Factory.create(menu).parent(self).renderTo(self.getContainerElm());
				self.fire('createmenu');
				self.menu.reflow();
				self.menu.on('cancel', function(e) {
					if (e.control === self.menu) {
						self.focus();
					}
				});

				self.menu.on('show hide', function(e) {
					if (e.control == self.menu) {
						self.activeMenu(e.type == 'show');
					}
				}).fire('show');

				self.aria('expanded', true);
			}

			self.menu.show();
			self.menu.layoutRect({w: self.layoutRect().w});
			self.menu.moveRel(self.getEl(), 'bl-tl');
		},

		hideMenu: function() {
			var self = this;

			if (self.menu) {
				self.menu.items().each(function(item) {
					if (item.hideMenu) {
						item.hideMenu();
					}
				});

				self.menu.hide();
				self.aria('expanded', false);
			}
		},

		activeMenu: function(state) {
			this.toggleClass('active', state);
		},

		renderHtml: function() {
			var self = this, id = self._id, prefix = self.classPrefix;
			var icon = self.settings.icon ? prefix + 'ico ' + prefix + 'i-' + self.settings.icon : '';

			self.aria('role', self.parent() instanceof MenuBar ? 'menuitem' : 'button');

			return (
				'<div id="' + id + '" class="' + self.classes() + '" tabindex="-1">' +
					'<button id="' + id + '-open" role="presentation" tabindex="-1">' +
						(icon ? '<i class="' + icon + '"></i>' : '') +
						(self._text ? (icon ? ' ' : '') + self.encode(self._text) : '') +
						' <i class="' + prefix + 'caret"></i>' +
					'</button>' +
				'</div>'
			);
		},

		postRender: function() {
			var self = this;

			self.on('click', function(e) {
				if (e.control === self && isChildOf(e.target, self.getEl())) {
					self.showMenu();

					if (e.keyboard) {
						self.menu.items()[0].focus();
					}
				}
			});

			self.on('mouseenter', function(e) {
				var overCtrl = e.control, parent = self.parent(), hasVisibleSiblingMenu;

				if (overCtrl && parent && overCtrl instanceof MenuButton && overCtrl.parent() == parent) {
					parent.items().filter('MenuButton').each(function(ctrl) {
						if (ctrl.hideMenu && ctrl != overCtrl) {
							if (ctrl.menu && ctrl.menu.visible()) {
								hasVisibleSiblingMenu = true;
							}

							ctrl.hideMenu();
						}
					});

					if (hasVisibleSiblingMenu) {
						overCtrl.showMenu();
					}
				}
			});

			return self._super();
		},

		text: function(text) {
			var self = this, i, children;

			if (self._rendered) {
				children = self.getEl('open').childNodes;
				for (i = 0; i < children.length; i++) {
					if (children[i].nodeType == 3) {
						children[i].data = text;
					}
				}
			}

			return this._super(text);
		},

		remove: function() {
			this._super();

			if (this.menu) {
				this.menu.remove();
			}
		}
	});

	return MenuButton;
});