/**
 * @requires jQuery
 * @requires CG
 * @requires CG.Event
 */

require(['jQuery', 'CG', 'CG.Event', 'CG.Overlay'], 'CG.TopBarDropdown');

(function($) {
	CG.TopBarDropdown = function(el) {
				
		var that = this,
			_el = $(el),
			_id = ++CG.TopBarDropdown.id_count,
			_topBar = _el.parents('#top_bar'),
			_title = _el.find('> a'),
			_container = _el.find('> .sub_content'),
			_overlay,
			_isOpen = false,
			_animating = CG.TopBarDropdown.animating,
			_openedOnce = false,
	
		/**
		 * Class constructor
		 * 
		 * @access private
		 * @return void
		 */
		_init = function() {
			
			//set up handlers
			$(document.body).click(_onDocumentClick);
			_title.click(_onClick);
			
			//hide and show overlays
			CG.TopBarDropdown.events.beforeShow.subscribe(_onBeforeShow);
			CG.TopBarDropdown.events.afterShow.subscribe(_onAfterShow);
			CG.TopBarDropdown.events.beforeHide.subscribe(_onBeforeHide);
			CG.TopBarDropdown.events.afterHide.subscribe(_onAfterHide);
			
			$.extend(that, {
				//properties
				_topBar: _topBar,
				_container: _container,
				_title: _title,

				//methods
				getId: _getId,
				show: _show,
				hide: _hide,
				toggle: _toggle,
				_checkId: _checkId
			});
		},
		
		/**
		 * Retrieve the id of this particular widget
		 * 
		 * @access public
		 * @return int 
		 */
		_getId = function() {
			return _id;
		},
		
		/**
		 * Check whether the arg matches the widget id
		 * 
		 * @access public
		 * @param int tempId The id to check
		 * @return boolean
		 */
		_checkId = function(tempId) {
			return tempId === _id;
		},
		
		/**
		 * Set the widget positioning in relation to the top bar
		 * 
		 * @access private
		 * @return void
		 */
		_setCSS = function() {
			_container.css('backgroundPosition', '-' + (_container.offset().left - ((_topBar.width() - 1194) / 2)) + 'px 1px');
		},
		
		/**
		 * Show the widget
		 * 
		 * @access public
		 * @fires CG.TopBarDropdown.events.beforeShow
		 * @fires CG.TopBarDropdown.events.afterShow
		 * @return CG.TopBarDropdown
		 */
		_show = function() {
			//make sure we're closed or no in the process of opening
			if(!_isOpen && !_animating) {
				_animating = true;

				//create the overlays if they don't exist
				if(!_overlay) {
					_overlay = CG.Overlay.getInstance();
				}
								
				//beforeShow custom event
				CG.TopBarDropdown.events.beforeShow.fire({id: _id});
				_container.slideDown(500, function() {
					_isOpen = true;
					_animating = false;
					
					//afterShow custom event
					CG.TopBarDropdown.events.afterShow.fire({id: _id});
				});
			}

			return that;
		},
	
		/**
		 * Hide the widget
		 * 
		 * @access public
		 * @fires CG.TopBarDropdown.events.beforeHide
		 * @fires CG.TopBarDropdown.events.afterHide
		 * @return CG.TopBarDropdown
		 */
		_hide = function() {
			//make sure we're open and not closing
			// also make sure, if this was a click event, that click did not originate in the widget
			if(_isOpen && !_animating) {
				_animating = true;
				
				//beforeHide custom event
				CG.TopBarDropdown.events.beforeHide.fire({id: _id});
				_container.slideUp(500, function() {
					_isOpen = false;
					_animating = false;

					//afterHide custom event
					CG.TopBarDropdown.events.afterHide.fire({id: _id});
				});	
			}

			return that;
		},
		
		/**
		 * Toggle the widget visibility
		 * 
		 * @access public
		 * @return CG.TopBarDropdown
		 */
		_toggle = function() {
			_isOpen ? _hide() : _show();
			return that;
		},
		
		/**
		 * Display the overlay before opening the dropdown
		 * 
		 * @access private
		 * @handles CG.TopBarDropdown.events.beforeShow
		 * @param CG.Event e
		 * @param object data
		 * @return void
		 */
		_onBeforeShow = function(e, data) {
			if(_checkId(data.id)) {
				CG.TopBarDropdown.animating = true;
				if(CG.TopBarDropdown.open_count == 0) {
					_overlay.show();
				}
				CG.TopBarDropdown.open_count++;
			}
		},
		
		/**
		 * Make any css corrections after opening the dropdown
		 * 
		 * @access private
		 * @handles CG.TopBarDropdown.events.afterShow
		 * @param CG.Event e
		 * @param object data
		 * @return void
		 */
		_onAfterShow = function(e, data) {
			if(_checkId(data.id)) {
				CG.TopBarDropdown.animating = false;
				if(!_openedOnce) {
					_setCSS();
				}
				_openedOnce = true;
			}
		},
		
		/**
		 * Set animation status before hiding the dropdown
		 * 
		 * @access private
		 * @handles CG.TopBarDropdown.events.beforeHide
		 * @param CG.Event e
		 * @param object data
		 * @return void
		 */
		_onBeforeHide = function(e, data) {
			if(_checkId(data.id)) {
				CG.TopBarDropdown.animating = true;
			}
		},
		
		/**
		 * Hide the overlay after hiding the dropdown
		 * 
		 * @access private
		 * @handles CG.TopBarDropdown.events.afterHide
		 * @param CG.Event e
		 * @param object data
		 * @return void
		 */
		_onAfterHide = function(e, data) {
			if(_checkId(data.id)) {
				CG.TopBarDropdown.open_count--;
				if(CG.TopBarDropdown.open_count == 0) {
					_overlay.hide();
				}
			
				CG.TopBarDropdown.animating = false;
			}
		},

		/**
		 * Toggle the visibility on a title click
		 * 
		 * @access private
		 * @handles _title.click
		 * @param jQuery.Event e
		 * @return void
		 */
		_onClick = function(e) {
			_toggle();
		},
		
		/**
		 * Hide the dropdown on a click originating outside of the widget
		 * 
		 * @access private
		 * @handles document.click
		 * @param jQuery.Event e
		 * @return mixed
		 */
		_onDocumentClick = function(e) {
			//added extra get for older jquery support
			if(e == undefined || (e.type == 'click' && $(e.target).parents().index(_container.get(0)) == -1)) {
				_hide();
			}
			
			if($(e.target).get(0) == _title.get(0)) {
				return false;
			}
		};
			
		_init();
	};
	
	$.extend(CG.TopBarDropdown, {
		id_count: 0,
		open_count: 0,
		animating: false,
		
		events: {
			beforeShow: new CG.Event(),
			afterShow: new CG.Event(),
			beforeHide: new CG.Event(),
			afterHide: new CG.Event()
		}
	});
})(jQuery);