'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var tslib_es6 = require('../../../../../tslib@2.3.0/node_modules/tslib/tslib.es6.js');
var event = require('../core/event.js');
var util = require('../core/util.js');
var Eventful = require('../core/Eventful.js');
var env = require('../core/env.js');

var TOUCH_CLICK_DELAY = 300;
var globalEventSupported = env.default.domSupported;
var localNativeListenerNames = (function () {
    var mouseHandlerNames = [
        'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout',
        'mouseup', 'mousedown', 'mousemove', 'contextmenu'
    ];
    var touchHandlerNames = [
        'touchstart', 'touchend', 'touchmove'
    ];
    var pointerEventNameMap = {
        pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1
    };
    var pointerHandlerNames = util.map(mouseHandlerNames, function (name) {
        var nm = name.replace('mouse', 'pointer');
        return pointerEventNameMap.hasOwnProperty(nm) ? nm : name;
    });
    return {
        mouse: mouseHandlerNames,
        touch: touchHandlerNames,
        pointer: pointerHandlerNames
    };
})();
var globalNativeListenerNames = {
    mouse: ['mousemove', 'mouseup'],
    pointer: ['pointermove', 'pointerup']
};
var wheelEventSupported = false;
function isPointerFromTouch(event) {
    var pointerType = event.pointerType;
    return pointerType === 'pen' || pointerType === 'touch';
}
function setTouchTimer(scope) {
    scope.touching = true;
    if (scope.touchTimer != null) {
        clearTimeout(scope.touchTimer);
        scope.touchTimer = null;
    }
    scope.touchTimer = setTimeout(function () {
        scope.touching = false;
        scope.touchTimer = null;
    }, 700);
}
function markTouch(event) {
    event && (event.zrByTouch = true);
}
function normalizeGlobalEvent(instance, event$1) {
    return event.normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event$1), true);
}
function isLocalEl(instance, el) {
    var elTmp = el;
    var isLocal = false;
    while (elTmp && elTmp.nodeType !== 9
        && !(isLocal = elTmp.domBelongToZr
            || (elTmp !== el && elTmp === instance.painterRoot))) {
        elTmp = elTmp.parentNode;
    }
    return isLocal;
}
var FakeGlobalEvent = (function () {
    function FakeGlobalEvent(instance, event) {
        this.stopPropagation = util.noop;
        this.stopImmediatePropagation = util.noop;
        this.preventDefault = util.noop;
        this.type = event.type;
        this.target = this.currentTarget = instance.dom;
        this.pointerType = event.pointerType;
        this.clientX = event.clientX;
        this.clientY = event.clientY;
    }
    return FakeGlobalEvent;
}());
var localDOMHandlers = {
    mousedown: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        this.__mayPointerCapture = [event$1.zrX, event$1.zrY];
        this.trigger('mousedown', event$1);
    },
    mousemove: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        var downPoint = this.__mayPointerCapture;
        if (downPoint && (event$1.zrX !== downPoint[0] || event$1.zrY !== downPoint[1])) {
            this.__togglePointerCapture(true);
        }
        this.trigger('mousemove', event$1);
    },
    mouseup: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        this.__togglePointerCapture(false);
        this.trigger('mouseup', event$1);
    },
    mouseout: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        var element = event$1.toElement || event$1.relatedTarget;
        if (!isLocalEl(this, element)) {
            if (this.__pointerCapturing) {
                event$1.zrEventControl = 'no_globalout';
            }
            this.trigger('mouseout', event$1);
        }
    },
    wheel: function (event$1) {
        wheelEventSupported = true;
        event$1 = event.normalizeEvent(this.dom, event$1);
        this.trigger('mousewheel', event$1);
    },
    mousewheel: function (event$1) {
        if (wheelEventSupported) {
            return;
        }
        event$1 = event.normalizeEvent(this.dom, event$1);
        this.trigger('mousewheel', event$1);
    },
    touchstart: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        markTouch(event$1);
        this.__lastTouchMoment = new Date();
        this.handler.processGesture(event$1, 'start');
        localDOMHandlers.mousemove.call(this, event$1);
        localDOMHandlers.mousedown.call(this, event$1);
    },
    touchmove: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        markTouch(event$1);
        this.handler.processGesture(event$1, 'change');
        localDOMHandlers.mousemove.call(this, event$1);
    },
    touchend: function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        markTouch(event$1);
        this.handler.processGesture(event$1, 'end');
        localDOMHandlers.mouseup.call(this, event$1);
        if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) {
            localDOMHandlers.click.call(this, event$1);
        }
    },
    pointerdown: function (event) {
        localDOMHandlers.mousedown.call(this, event);
    },
    pointermove: function (event) {
        if (!isPointerFromTouch(event)) {
            localDOMHandlers.mousemove.call(this, event);
        }
    },
    pointerup: function (event) {
        localDOMHandlers.mouseup.call(this, event);
    },
    pointerout: function (event) {
        if (!isPointerFromTouch(event)) {
            localDOMHandlers.mouseout.call(this, event);
        }
    }
};
util.each(['click', 'dblclick', 'contextmenu'], function (name) {
    localDOMHandlers[name] = function (event$1) {
        event$1 = event.normalizeEvent(this.dom, event$1);
        this.trigger(name, event$1);
    };
});
var globalDOMHandlers = {
    pointermove: function (event) {
        if (!isPointerFromTouch(event)) {
            globalDOMHandlers.mousemove.call(this, event);
        }
    },
    pointerup: function (event) {
        globalDOMHandlers.mouseup.call(this, event);
    },
    mousemove: function (event) {
        this.trigger('mousemove', event);
    },
    mouseup: function (event) {
        var pointerCaptureReleasing = this.__pointerCapturing;
        this.__togglePointerCapture(false);
        this.trigger('mouseup', event);
        if (pointerCaptureReleasing) {
            event.zrEventControl = 'only_globalout';
            this.trigger('mouseout', event);
        }
    }
};
function mountLocalDOMEventListeners(instance, scope) {
    var domHandlers = scope.domHandlers;
    if (env.default.pointerEventsSupported) {
        util.each(localNativeListenerNames.pointer, function (nativeEventName) {
            mountSingleDOMEventListener(scope, nativeEventName, function (event) {
                domHandlers[nativeEventName].call(instance, event);
            });
        });
    }
    else {
        if (env.default.touchEventsSupported) {
            util.each(localNativeListenerNames.touch, function (nativeEventName) {
                mountSingleDOMEventListener(scope, nativeEventName, function (event) {
                    domHandlers[nativeEventName].call(instance, event);
                    setTouchTimer(scope);
                });
            });
        }
        util.each(localNativeListenerNames.mouse, function (nativeEventName) {
            mountSingleDOMEventListener(scope, nativeEventName, function (event$1) {
                event$1 = event.getNativeEvent(event$1);
                if (!scope.touching) {
                    domHandlers[nativeEventName].call(instance, event$1);
                }
            });
        });
    }
}
function mountGlobalDOMEventListeners(instance, scope) {
    if (env.default.pointerEventsSupported) {
        util.each(globalNativeListenerNames.pointer, mount);
    }
    else if (!env.default.touchEventsSupported) {
        util.each(globalNativeListenerNames.mouse, mount);
    }
    function mount(nativeEventName) {
        function nativeEventListener(event$1) {
            event$1 = event.getNativeEvent(event$1);
            if (!isLocalEl(instance, event$1.target)) {
                event$1 = normalizeGlobalEvent(instance, event$1);
                scope.domHandlers[nativeEventName].call(instance, event$1);
            }
        }
        mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { capture: true });
    }
}
function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) {
    scope.mounted[nativeEventName] = listener;
    scope.listenerOpts[nativeEventName] = opt;
    event.addEventListener(scope.domTarget, nativeEventName, listener, opt);
}
function unmountDOMEventListeners(scope) {
    var mounted = scope.mounted;
    for (var nativeEventName in mounted) {
        if (mounted.hasOwnProperty(nativeEventName)) {
            event.removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]);
        }
    }
    scope.mounted = {};
}
var DOMHandlerScope = (function () {
    function DOMHandlerScope(domTarget, domHandlers) {
        this.mounted = {};
        this.listenerOpts = {};
        this.touching = false;
        this.domTarget = domTarget;
        this.domHandlers = domHandlers;
    }
    return DOMHandlerScope;
}());
var HandlerDomProxy = (function (_super) {
    tslib_es6.__extends(HandlerDomProxy, _super);
    function HandlerDomProxy(dom, painterRoot) {
        var _this = _super.call(this) || this;
        _this.__pointerCapturing = false;
        _this.dom = dom;
        _this.painterRoot = painterRoot;
        _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers);
        if (globalEventSupported) {
            _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers);
        }
        mountLocalDOMEventListeners(_this, _this._localHandlerScope);
        return _this;
    }
    HandlerDomProxy.prototype.dispose = function () {
        unmountDOMEventListeners(this._localHandlerScope);
        if (globalEventSupported) {
            unmountDOMEventListeners(this._globalHandlerScope);
        }
    };
    HandlerDomProxy.prototype.setCursor = function (cursorStyle) {
        this.dom.style && (this.dom.style.cursor = cursorStyle || 'default');
    };
    HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) {
        this.__mayPointerCapture = null;
        if (globalEventSupported
            && ((+this.__pointerCapturing) ^ (+isPointerCapturing))) {
            this.__pointerCapturing = isPointerCapturing;
            var globalHandlerScope = this._globalHandlerScope;
            isPointerCapturing
                ? mountGlobalDOMEventListeners(this, globalHandlerScope)
                : unmountDOMEventListeners(globalHandlerScope);
        }
    };
    return HandlerDomProxy;
}(Eventful.default));

exports.default = HandlerDomProxy;
