/*!
 * jQuery UI Mouse @VERSION
 *
 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 *
 * patched from:
 * https://github.com/cscott/jquery-ui/commit/3744712e13271fa06a502be19bb8b3854fe66c59
 * and improved by Alpha Solutions
 */
(function( $, undefined ) {

    var supportTouches = ($.browser.webkit && navigator.userAgent.indexOf("Mobile") != -1); ;

var mouseHandled = false;
$(document).mousedown(function(e) {
	mouseHandled = false;
});

    $.widget("ui.mouse", {
        options: {
            cancel: ':input,option',
            distance: 1,
            delay: 0
        },

        _eventNames: {
            start: 'mousedown',
            drag: 'mousemove',
            stop: 'mouseup'
        },

        _supportTouchesEvent: function (event) {

            if (event.type == 'touchend' && this._mouseStarted)
                event = this._prevEvent;

            var t = event.originalEvent.touches;
            return !supportTouches || (t.length == 1 ? (this._prevEvent = $.extend(event, {
                target: t[0].target,
                pageX: t[0].pageX,
                pageY: t[0].pageY
            })) : false);

        },

        _mouseInit: function () {
            var self = this;

            supportTouches && (this._eventNames = {
                start: 'touchstart',
                drag: 'touchmove',
                stop: 'touchend'
            });

            this.element
			.bind(this._eventNames.start + '.' + this.widgetName, function (event) {
			    return self._supportTouchesEvent(event) && self._mouseDown(event);
			})
			.bind('click.' + this.widgetName, function (event) {
				if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
				    $.removeData(event.target, self.widgetName + '.preventClickEvent');
			        event.stopImmediatePropagation();
			        return false;
			    }
			});

            this.started = false;
        },

        // TODO: make sure destroying one instance of mouse doesn't mess with
        // other instances of mouse
        _mouseDestroy: function () {
            this.element.unbind('.' + this.widgetName);
        },

        _mouseDown: function (event) {
            // don't let more than one widget handle mouseStart
		if(mouseHandled) {return};

            // we may have missed mouseup (out of window)
            (this._mouseStarted && this._mouseUp(event));

            this._mouseDownEvent = event;

            var self = this,
			btnIsLeft = (event.which == 1 || supportTouches),
			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).closest(this.options.cancel).length : false);
            if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
                return true;
            }

            this.mouseDelayMet = !this.options.delay;
            if (!this.mouseDelayMet) {
                this._mouseDelayTimer = setTimeout(function () {
                    self.mouseDelayMet = true;
                }, this.options.delay);
            }

            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted = (this._mouseStart(event) !== false);
                if (!this._mouseStarted) {
                    event.preventDefault();
                    return true;
                }
            }

		// Click event may never have fired (Gecko & Opera)
		if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
			$.removeData(event.target, this.widgetName + '.preventClickEvent');
		}
            // these delegates are required to keep context
            this._mouseMoveDelegate = function (event) {
                return self._supportTouchesEvent(event) && self._mouseMove(event);
            };
            this._mouseUpDelegate = function (event) {
                return self._supportTouchesEvent(event) && self._mouseUp(event);
            };
            $(document)
			.bind(this._eventNames.drag + '.' + this.widgetName, this._mouseMoveDelegate)
			.bind(this._eventNames.stop + '.' + this.widgetName, this._mouseUpDelegate);

            // preventDefault() is used to prevent the selection of text here -
            // however, in Safari, this causes select boxes not to be selectable
            // anymore, so this fix is needed
            (($.browser.safari && !supportTouches) || event.preventDefault());
		
		mouseHandled = true;
            return true;
        },

        _mouseMove: function (event) {
            // IE mouseup check - mouseup happened when mouse was out of window
		if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
                return this._mouseUp(event);
            }

            if (this._mouseStarted) {
                this._mouseDrag(event);
                return event.preventDefault();
            }

            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, event) !== false);
                (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
            }

            return !this._mouseStarted;
        },

        _mouseUp: function (event) {
            $(document)
			.unbind(this._eventNames.drag + '.' + this.widgetName, this._mouseMoveDelegate)
			.unbind(this._eventNames.stop + '.' + this.widgetName, this._mouseUpDelegate);

		if (this._mouseStarted) {
			this._mouseStarted = false;

			if (event.target == this._mouseDownEvent.target) {
			    $.data(event.target, this.widgetName + '.preventClickEvent', true);
			}

			this._mouseStop(event);
		}

            return false;
        },

        _mouseDistanceMet: function (event) {
            return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
			) >= this.options.distance
		);
        },

        _mouseDelayMet: function (event) {
            return this.mouseDelayMet;
        },

        // These are placeholder methods, to be overriden by extending plugin
        _mouseStart: function (event) { },
        _mouseDrag: function (event) { },
        _mouseStop: function (event) { },
        _mouseCapture: function (event) { return true; }
    });

})(jQuery);
