"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var HaikuBase_1 = require("./../../HaikuBase");
var mixpanelInit_1 = require("./mixpanelInit");
var createRightClickMenu_1 = require("./createRightClickMenu");
var getElementSize_1 = require("./getElementSize");
var getLocalDomEventPosition_1 = require("./getLocalDomEventPosition");
var patch_1 = require("./patch");
var render_1 = require("./render");
var HaikuDOMRenderer = (function (_super) {
    __extends(HaikuDOMRenderer, _super);
    function HaikuDOMRenderer(mount, config) {
        var _this = _super.call(this) || this;
        _this.mount = mount;
        _this.user = {
            mouse: {
                x: 0,
                y: 0,
                down: 0,
                buttons: [0, 0, 0],
            },
            keys: {},
            touches: [],
            mouches: [],
        };
        _this.config = config;
        _this.shouldCreateContainer = true;
        return _this;
    }
    HaikuDOMRenderer.prototype.render = function (virtualContainer, virtualTree, component) {
        return render_1.default(this.mount, virtualContainer, virtualTree, component);
    };
    HaikuDOMRenderer.prototype.patch = function (patchesDict, component) {
        return patch_1.default(this.mount, patchesDict, component);
    };
    HaikuDOMRenderer.prototype.menuize = function (component) {
        return createRightClickMenu_1.default(this.mount, component);
    };
    HaikuDOMRenderer.prototype.mixpanel = function (mixpanelToken, component) {
        return mixpanelInit_1.default(mixpanelToken, component);
    };
    HaikuDOMRenderer.prototype.hasSizing = function () {
        return this.config && this.config.sizing && this.config.sizing !== 'normal';
    };
    HaikuDOMRenderer.prototype.getZoom = function () {
        return ((this.config && this.config.zoom) || 1.0);
    };
    HaikuDOMRenderer.prototype.getPan = function () {
        return {
            x: (this.config && this.config.pan && this.config.pan.x) || 0,
            y: (this.config && this.config.pan && this.config.pan.y) || 0,
        };
    };
    HaikuDOMRenderer.prototype.createContainer = function (out) {
        if (out === void 0) { out = {}; }
        var size;
        if (this.mount) {
            size = getElementSize_1.default(this.mount);
        }
        else {
            console.warn('[haiku dom renderer] mount empty; using fallback size');
            size = { x: 1, y: 1 };
        }
        out['layout'] = {
            computed: {
                size: size,
            },
        };
        if (!this.hasSizing() || !this.config.alwaysComputeSizing) {
            this.shouldCreateContainer = false;
        }
        return out;
    };
    HaikuDOMRenderer.prototype.initialize = function () {
        var _this = this;
        var user = this.user;
        var setMouse = function (mouseEvent) {
            var topElement = _this.mount.childNodes[0];
            if (topElement) {
                var pos = getLocalDomEventPosition_1.default(mouseEvent, topElement);
                user.mouse.x = pos.x;
                user.mouse.y = pos.y;
            }
        };
        var setTouches = function (touchEvent) {
            user.touches.splice(0);
            var topElement = _this.mount.childNodes[0];
            if (topElement) {
                for (var i = 0; i < touchEvent.touches.length; i++) {
                    var touch = touchEvent.touches[i];
                    var pos = getLocalDomEventPosition_1.default(touch, topElement);
                    user.touches.push(pos);
                }
            }
        };
        var setMouches = function () {
            user.mouches.splice(0);
            if (user.mouse.down) {
                user.mouches.push(user.mouse);
            }
            user.mouches.push.apply(user.mouches, user.touches);
        };
        var clearKey = function () {
            for (var which in user.keys) {
                user.keys[which] = 0;
            }
        };
        var clearMouse = function () {
            user.mouse.down = 0;
            user.touches.splice(0);
            for (var i = 0; i < user.mouse.buttons.length; i++) {
                user.mouse.buttons[i] = 0;
            }
        };
        var clearMouch = function () {
            user.mouches.splice(0);
        };
        var clearTouch = function () {
            user.touches.splice(0);
        };
        var doc = this.mount.ownerDocument;
        var win = doc.defaultView || doc.parentWindow;
        this.mount.addEventListener('mousedown', function (mouseEvent) {
            ++user.mouse.down;
            ++user.mouse.buttons[mouseEvent.button];
            setMouse(mouseEvent);
            setMouches();
        });
        this.mount.addEventListener('mouseup', function (mouseEvent) {
            clearMouse();
            clearMouch();
            setMouches();
        });
        win.addEventListener('mousemove', function (mouseEvent) {
            setMouse(mouseEvent);
            setMouches();
        });
        win.addEventListener('mouseenter', function (mouseEvent) {
            clearMouse();
            clearMouch();
        });
        win.addEventListener('mouseleave', function (mouseEvent) {
            clearMouse();
            clearMouch();
        });
        this.mount.addEventListener('wheel', function (mouseEvent) {
            setMouse(mouseEvent);
            setMouches();
        }, {
            passive: true,
        });
        doc.addEventListener('keydown', function (keyEvent) {
            if (user.keys[keyEvent.which] === undefined) {
                user.keys[keyEvent.which] = 0;
            }
            ++user.keys[keyEvent.which];
        });
        doc.addEventListener('keyup', function (keyEvent) {
            if (user.keys[keyEvent.which] === undefined) {
                user.keys[keyEvent.which] = 0;
            }
            if (keyEvent.which === 91 || keyEvent.which === 17) {
                clearKey();
            }
            user.keys[keyEvent.which] = 0;
        });
        if (this.hasSizing() && !this.config.alwaysComputeSizing) {
            win.addEventListener('resize', function () {
                _this.shouldCreateContainer = true;
            });
            win.addEventListener('orientationchange', function () {
                _this.shouldCreateContainer = true;
            });
        }
        win.addEventListener('blur', function (blurEvent) {
            clearKey();
            clearMouse();
            clearTouch();
            clearMouch();
        });
        win.addEventListener('focus', function (blurEvent) {
            clearKey();
            clearMouse();
            clearTouch();
            clearMouch();
        });
        win.addEventListener('touchstart', function (touchEvent) {
            setTouches(touchEvent);
            setMouches();
        }, {
            passive: true,
        });
        win.addEventListener('touchend', function (touchEvent) {
            clearTouch();
            clearMouch();
        });
        win.addEventListener('touchmove', function (touchEvent) {
            setTouches(touchEvent);
            setMouches();
        }, {
            passive: true,
        });
        win.addEventListener('touchenter', function (touchEvent) {
            clearTouch();
            clearMouch();
        });
        win.addEventListener('touchleave', function (touchEvent) {
            clearTouch();
            clearMouch();
        });
    };
    HaikuDOMRenderer.prototype.mountEventListener = function (selector, name, listener) {
        var _this = this;
        this.mount.addEventListener(name, function (domEvent) {
            if (!selector || selector === HaikuBase_1.GLOBAL_LISTENER_KEY ||
                !domEvent || !domEvent.target) {
                listener(null, domEvent);
                return;
            }
            var query = selector;
            if (selector.slice(0, 6) === 'haiku:') {
                query = "[haiku-id=\"" + selector.slice(6) + "\"]";
            }
            var match = _this.mount.querySelector(query);
            if (match) {
                if (match === domEvent.target ||
                    (match.contains && match.contains(domEvent.target))) {
                    listener(domEvent.target, domEvent);
                    return;
                }
            }
        });
    };
    HaikuDOMRenderer.prototype.getUser = function () {
        var zoom = this.getZoom();
        var pan = this.getPan();
        return {
            zoom: zoom,
            pan: pan,
            mouse: {
                x: (this.user.mouse.x) / zoom,
                y: (this.user.mouse.y) / zoom,
                down: this.user.mouse.down,
                buttons: this.user.mouse.buttons.slice(),
            },
            keys: __assign({}, this.user.keys),
            touches: this.user.touches.slice(),
            mouches: this.user.mouches.slice(),
        };
    };
    return HaikuDOMRenderer;
}(HaikuBase_1.default));
exports.default = HaikuDOMRenderer;
//# sourceMappingURL=HaikuDOMRenderer.js.map