angular.module('doubleTap', [])
  
.directive('doubleTapConfirm', function ($timeout) {
	var processDefaults = function(attrs){
		if(!attrs.doubleTapTimeout){attrs.doubleTapTimeout = 3000;}
	};
	return {
		restrict: 'A',		
		scope: true,
		link: function(scope, element, attrs) {
			//Add default values, if not provided by the element
			processDefaults(attrs);

			//Initialize 			
			scope.clicks = 0; //Number of times this element has been clicked
			scope.selected = false; //If the element is considered "selected"
			scope.confirmed = false; //If a double tap has been confirmed
			scope.globallyConfirmed = false; //If a double tap has been confirmed by any element using this directive
			scope.clickPromise = null; //When a click event occurs we may want to cancel the $timeout

			//BroadcastListeners
			scope.$on("reset",function(){
				scope.clicks = 0; 
				scope.selected = false; 
				scope.confirmed = false;
				scope.globallyConfirmed = false;
				$timeout.cancel(scope.clickPromise);
				scope.clickPromise = null; 
			});
			scope.$on("doubleTapReset",function(event,sender){
				//The sender of this directive uses its unique $id value provided by Angular

				//Deselect all elements using the doubleTapConfirm directive
				scope.selected = false;
				if(sender !== scope.$id){
					//Cancel the timer and set the element's number of clicks to 0
					$timeout.cancel(scope.clickPromise);
					scope.clicks = 0;
	        	}
	        	else{
	        		//Indicate that the sender is now selected
	        		scope.selected = true;
	        	}
	        	//Notify watchers
		        scope.$digest();
			});
			scope.$on("doubleTapConfirmed",function(event,sender){
				//The sender of this directive uses its unique $id value provided by Angular
				if(sender == scope.$id){
					scope.confirmed = true;
				}
				//Globally confirm to all elements that some element has been doubletapped
				scope.globallyConfirmed = true;
			});

			//Click event
            element.bind('click', function() {            	
            	scope.clicks++;         	
            	if(scope.clicks == 2){
            		//Double tap is reached, the element should not be reset to 0 clicks after its timeout period.  
            		$timeout.cancel(scope.clickPromise);
            		//Confirm the double tap to all other elements 
            		//Change to $root if elements are not on the same DOM level
            		scope.$parent.$broadcast("doubleTapConfirmed",scope.$id);
            		//Execute what is bound in the double-tap-confirmed attribute 
            		scope.$apply(attrs.doubleTapConfirm);
            		
            		var ePopup = attrs.dblmodalOpen;
            		scope.$apply($(ePopup).find('input').filter("[modal-open]").attr('re-open', ePopup));
					var title = $(ePopup).find('> .title').html();
					var modal = JSON.parse($(ePopup).attr('data-dialog-modal'));
					var width = $(ePopup).attr('data-dialog-width');
					var options = {
					   rounded: '10px',
					   title: title,
					   messageType: 'none',
					   width: (width == undefined ? 550 : width),
					   modal: modal,
					   overlayColor: '#000000',
					   overlayTransparent: .85
					}
					var popup = $(ePopup).dialog(options);
					popup.switchStateDialog("open");
					$(ePopup).find('.dismis-popup').click(function() {
					   popup.switchStateDialog("close");
					})

            	}else{
            		//Invoke a timeout that will reset the element to 0 clicks after a certain time
            		scope.clickPromise = $timeout(function(){
	            		scope.clicks = 0;
						scope.selected = false;
						scope.confirmed = false;
						scope.globallyConfirmed = false;
	            		scope.$digest();
	            	},attrs.doubleTapTimeout); //The timeout time set from the elements attribute
            	}  
            	//Broadcast the changes
            	scope.$digest();  
            	//Change to $root if elements are not on the same DOM level
            	//Include scope.$id to know which element sent the broadcast
            	scope.$parent.$broadcast("doubleTapReset",scope.$id);
            });
        }
	}
});