jui.defineUI("ui.dropdown", [ "jquery" ], function($) {

	var hideAll = function() {
		var dd = getDropdown();

		if(dd != null) {
			dd.hide();
		}
	}

	var getDropdown = function() {
		var call_list = jui.get("ui.dropdown");

		for(var i = 0; i < call_list.length; i++) {
			var ui_list = call_list[i];

			for(var j = 0; j < ui_list.length; j++) {
				if(ui_list[j].type == "show") return ui_list[j];
			}
		}

		return null;
	}

	$(function() {
		document.addEventListener("click", function(e) {
			var tn = e.target.tagName;

			if(tn != "LI" && tn != "INPUT" && tn != "A" && tn != "BUTTON" && tn != "I") {
				hideAll();
			}
		});

		window.addEventListener("keydown", function(e) {
			var dd = getDropdown();

			if(dd != null) {
				dd.wheel(e.which, function() {
					e.preventDefault();
				});
			}
		});
	});


    /**
     * @class ui.dropdown
     * Dropdown is a UI component that is frequently used in multiple UI components such as combo box, navigation, table, ect
     *
     * @extends core
     * @alias Dropdown
     * @requires jquery
     *
     */
	var UI = function() {
		var ui_list = null, index = -1;

		function setEventNodes(self) {
			var $list = $(ui_list.menu).find("li");

			// 이벤트 걸린거 초기화
			$list.off("click").off("hover");

			// 클릭 이벤트 설정
			self.addEvent($list, "click", function(e) {
				if($(this).hasClass("divider") || $(this).hasClass("title") || $(this).hasClass("disabled")) return;

				var index = getTargetIndex(this),
					text = $(this).text(),
					value = $(this).attr("value");

				self.emit("change", [ { index: index, value: value, text: text }, e ]);

				// close가 true일 경우, 전체 드롭다운 숨기기
				if(self.options.close) hideAll();

				// A 태그일 경우에는 이벤트 막기
				if(e.target.tagName == "A") {
					e.preventDefault();
				}
			});

			// 마우스 오버시 hover 클래스 제거
			self.addEvent($list, "hover", function(e) {
				$list.removeClass("active");
			});

			function getTargetIndex(elem) {
				var result = 0;

				$list.each(function(i) {
					if(elem == this) {
						result = i;
					}
				});

				return result;
			}
		}

		function selectItem(self, callback) {
			var $list = ui_list.menu.find("li"),
				$target = $list.eq(index);

			$list.removeClass("active");

			if($target.val() != "" || $target.html() != "") {
				$target.addClass("active");

				if(self.options.height > 0) {
					ui_list.menu.scrollTop(index * $target.outerHeight());
				}
			} else {
				if(typeof(callback) == "function") {
					callback();
				}
			}
		}

		this.init = function() {
			var opts = this.options;

			var $dd_root = $(this.root),
				$dd_menu = $dd_root.find("ul"),
				$dd_anchor = $dd_root.find(".anchor");

			// 메인 설정, 없을 경우에는 root가 메인이 됨
			$dd_menu = ($dd_menu.length == 0) ? $dd_root : $dd_menu;

			// UI 객체 추가
			ui_list = { root: $dd_root, menu: $dd_menu, anchor: $dd_anchor };

			// Size
			ui_list.root.outerWidth(ui_list.menu.outerWidth());

			// Width
			if(opts.width > 0) {
				$dd_menu.outerWidth(opts.width);
			}

			// Height
			if(opts.height > 0) {
				$dd_menu.css({ "maxHeight": opts.height, "overflow": "auto" });
			}

			// Left
			if(opts.left > 0) {
				$dd_root.css("left", opts.left);
			}

			// Top
			if(opts.top > 0) {
				$dd_root.css("top", opts.top);
			}

			// Default Styles
			$dd_menu.css({ "display": "block" });
			$dd_root.css({ "position": "absolute", "display": "none" });

			// 드롭다운 목록 갱신
			if(opts.nodes.length > 0) {
				this.update(opts.nodes);
			} else {
				setEventNodes(this);
			}

			this.type = "hide"; // 기본 타입 설정
		}

        /**
         * @method update
         * Changes the dropdown list
         *
         * @param {Array} nodes Dropdown list
         */
		this.update = function(nodes) {
			if(!this.tpl.node) return;

			$(ui_list.menu).empty();

			for(var i = 0; i < nodes.length; i++) {
				$(ui_list.menu).append(this.tpl.node(nodes[i]));
			}

			setEventNodes(this);
		}

        /**
         * @method hide
         * Hides the dropdown
         */
		this.hide = function() {
			ui_list.root.hide();

			this.emit("hide");
			this.type = "hide";
		}

        /**
         * @method show
         * Shows a dropdown at the specified coordinates
         *
         * @param {Integer} x
         * @param {Integer} y
         */
		this.show = function(x, y) {
			hideAll();

			ui_list.root.show();

			// Anchor 옵션 처리
			if(ui_list.anchor.length > 0)
				ui_list.root.css("margin-top", "10px");

			// x, y 값이 있을 경우
			if(arguments.length == 2) {
				this.move(x, y);
			}

			this.emit("show");
			this.type = "show";
		}

        /**
         * @method move
         * Moves a dropdown to the specified coordinates
         *
         * @param {Integer} x
         * @param {Integer} y
         */
		this.move = function(x, y) {
			ui_list.root.css("left", x);
			ui_list.root.css("top", y);
		}

        /**
         * @method wheel
         * Changes a selected node upwards when the key is set to -1, or downwards when the key is set to 1. If the key is set to 0, the speciified node is selected
         *
         * @param {Integer} key
         * @param {Function} callback
         */
		this.wheel = function(key, callback) {
			if(!this.options.keydown) return;

			var self = this,
				$list = ui_list.menu.find("li");

			// 탭을 눌렀을 경우, 드롭다운 숨기기
			if(key == 9) {
				this.hide();
				return;
			}

			if(key == 38 || key == -1) { // up
				if(index < 1) index = $list.length - 1;
				else index--;

				selectItem(this, function() {
					index--;
					selectItem(self);
				});

				if(callback) callback();
			}

			if(key == 40 || key == 1) { // down
				if(index < $list.length - 1) index++;
				else index = 0;

				selectItem(self, function() {
					index++;
					selectItem(self);
				});

				if(callback) callback();
			}

			if(key == 13 || key == 0 || !key) { // enter
				self.addTrigger($list.eq(index), "click");
				index = -1;

				if(callback) callback();
			}
		}

        /**
         * @method reload
         * Reloads the dropdown list
         */
		this.reload = function() {
			this.init();
			this.emit("reload");
		}
	}

    UI.setup = function() {
        return {
            /**
             * @cfg {Boolean} [close=true]
             * Closes the Auto when clicking on the dropdown list
             */
			close: true,

            /**
             * @cfg {Boolean} [keydown=false]
             * It is possible to choose anything on the dropdown list with the arrow keys on the keyboard
             */
			keydown: false,

            /**
             * @cfg {Integer} [left=0]
             * Sets the X coordinate of the dropdown list
             */
			left: 0,

            /**
             * @cfg {Integer} [top=0]
             * Sets the Y coordinate of the dropdown list
             */
			top: 0,

            /**
             * @cfg {Integer} [width=0]
             * Determines the horizontal size of a dropdown list
             */
			width: 0,

            /**
             * @cfg {Integer} [height=0]
             * Determines the vertical size of a dropdown list
             */
			height: 0,

            /**
             * @cfg {Array} nodes
             * Sets a dropdown list to data rather than markup
             */
			nodes: []
        }
    }

    /**
     * @event change
     * Event that occurs when anything on the dropdown list is selected
     *
     * @param {Object} data
     * @param {EventObject} e The event object
     */

    /**
     * @event show
     * Event that occurs when a dropdown is shown
     */

    /**
     * @event hide
     * Event that occurs when a dropdown is hidden
     */

    /**
     * @event reload
     * Event that occurs when a dropdown is reloaded
     */

	return UI;
});