/* Copyright 2009 Palm, Inc.  All rights reserved. */


var TapHandler = Class.create({
	initialize: function(element){
		this.element = element;
		this.handlers = [];
		this.defaultHandler = null;
		this.eventsTapHandler = this.handleEventsTap.bindAsEventListener(this);
		this.eventsHoldHandler = this.handleEventsHold.bindAsEventListener(this);
		this.eventsDragStartHandler = this.handleEventsDragStart.bindAsEventListener(this);
		this.eventsDraggingHandler = this.handleEventsDragging.bindAsEventListener(this);
		this.eventsDragEndHandler = this.handleEventsDragEnd.bindAsEventListener(this);
	},
	
	activate: function() {
		this.element.observe(Mojo.Event.tap, this.eventsTapHandler);
		this.element.observe(Mojo.Event.hold, this.eventsHoldHandler);
		this.element.observe(Mojo.Event.dragStart, this.eventsDragStartHandler);
		this.element.observe(Mojo.Event.dragging, this.eventsDraggingHandler);
		this.element.observe(Mojo.Event.dragEnd, this.eventsDragEndHandler);
	},
	
	deactivate: function() {
		this.element.stopObserving(Mojo.Event.tap, this.eventsTapHandler);
		this.element.stopObserving(Mojo.Event.hold, this.eventsHoldHandler);
		this.element.stopObserving(Mojo.Event.dragStart, this.eventsDragStartHandler);
		this.element.stopObserving(Mojo.Event.dragging, this.eventsDraggingHandler);
		this.element.stopObserving(Mojo.Event.dragEnd, this.eventsDragEndHandler);
		this.clearSelected();
	},
	
	removeAllHandlers: function() {
		this.handlers = [];
	},
	
	addHandler: function(left, top, right, bottom, 
												tapCallback, 
												selectedCallback, 
												clearCallback, 
												holdCallback, 
												startDragCallback,
												draggingCallback,
												endDragCallback){
		this.handlers.push({left: left, 
							top: top, 
							right: right, 
							bottom: bottom, 
							tapFunc: tapCallback, 
							selectedFunc: selectedCallback, 
							clearFunc: clearCallback,
							holdFunc: holdCallback,
							startDragFunc: startDragCallback,
							draggingFunc: draggingCallback,
							endDragFunc: endDragCallback});
	},
	
	setDefaultHandler: function(tapCallback, selectedCallback, clearCallback){
		this.defaultHandler = {tapFunc: tapCallback, 
							   selectedFunc: selectedCallback,
							   clearFunc: clearCallback,
							   holdFunc: null,
							   startDragFunc: null,
								 draggingFunc: null,
								 endDragFunc: null};
	},
	
	clearSelected: function() {
		if (this.selected) {
			if (this.selected.clearFunc)
				this.selected.clearFunc();
			this.selected = null;
		}
	},
	
	handleEventsDragStart: function(event){
		//Mojo.Log.info("tap_handler: handleEventsDragStart");
		var elementPos = Mojo.View.viewportOffset(this.element);
		var x = event.down.x - elementPos.left;
		var y = event.down.y - elementPos.top;
		this.dragHandler = null;
		var handler = this.hitTest(x, y);
		if (handler) {
			this.dragHandler = handler;
			if (handler.startDragFunc) {
		  	return handler.startDragFunc(event);
		  }
		}
		this.clearSelected();
	},
	
	handleEventsDragging: function(event) {
		//Mojo.Log.info("tap_handler: handleEventsDragging");
		var elementPos = Mojo.View.viewportOffset(this.element);
		if (this.dragHandler) {
			if (this.dragHandler.draggingFunc) {
				return this.dragHandler.draggingFunc(event);
			}
		}
	},
	
	handleEventsDragEnd: function(event) {
		//Mojo.Log.info("tap_handler: handleEventsDragEnd");
		var elementPos = Mojo.View.viewportOffset(this.element);
		var x = event.up.x - elementPos.left;
		var y = event.up.y - elementPos.top;
		var handler = this.hitTest(x, y);
		if (this.dragHandler) {
			if (this.dragHandler.endDragFunc) {
				return this.dragHandler.endDragFunc(event);
			}
		}
 	},
	
	handleEventsHold: function(event){
		//Mojo.Log.info("tap_handler: handleEventsHold");
		var elementPos = Mojo.View.viewportOffset(this.element);
		var x = event.down.x - elementPos.left;
		var y = event.down.y - elementPos.top;
		
		var handler = this.hitTest(x, y);
		if (handler) {
			if (handler.selectedFunc) {
				this.selected = handler;
				handler.selectedFunc();
			}
			if (handler.holdFunc) {
				handler.holdFunc();
			}
		} else if (this.defaultHandler) {
			if (this.defaultHandler.selectedFunc) {
				this.selected = this.defaultHandler;
				this.defaultHandler.selectedFunc(x, y);
			}
		}
		
		// Do NOT call Event.stop(event) in this function.  For some
		// reason, doing so, causes the subsequent tap/holdEnd events
		// related to this hold event from happening
	},
	
	handleEventsTap: function(event){
		//Mojo.Log.info("tap_handler: handleEventsTap");
		// Ignore all subsequent taps in a multi-tap (i.e. ignore the 2nd
		// tap of a double-tap).  We treat multi-taps as a single tap.
		if (event.down.detail > 1) {
			Event.stop(event);
			return;
		}
		var elementPos = Mojo.View.viewportOffset(this.element);
		var x = event.down.x - elementPos.left;
		var y = event.down.y - elementPos.top;
		
		var handler = this.hitTest(x, y);
		if (handler) {
			if (!this.selected) {
				if (handler.selectedFunc) {
					this.selected = handler;
					handler.selectedFunc();
				}
			}
			if (handler.tapFunc) {
				handler.tapFunc(event);
			}	
		} else if (this.defaultHandler) {
			if (!this.selected) {
				if (this.defaultHandler.selectedFunc) {
					this.selected = this.defaultHandler;
					this.defaultHandler.selectedFunc();
				}
			}
			if (this.defaultHandler.tapFunc) {
				this.defaultHandler.tapFunc(event, x, y);
			}	
		}
	},
	
	hitTest: function(x, y) {
		for (var i = 0; i < this.handlers.length; i++) {
			var handler = this.handlers[i];
			if ((y >= handler.top) &&
				(y <= handler.bottom) &&
				(x >= handler.left) &&
				(x <= handler.right))
				return handler;
		}
		return null;
	},

});