"use strict";
var __assign = (this && this.__assign) || function () {
    __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;
    };
    return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    }
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        }
        finally { if (e) throw e.error; }
    }
    return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Heatmaps = void 0;
var rageclick_1 = __importDefault(require("./extensions/rageclick"));
var globals_1 = require("./utils/globals");
var autocapture_utils_1 = require("./autocapture-utils");
var constants_1 = require("./constants");
var core_1 = require("@posthog/core");
var logger_1 = require("./utils/logger");
var element_utils_1 = require("./utils/element-utils");
var dead_clicks_autocapture_1 = require("./extensions/dead-clicks-autocapture");
var core_2 = require("@posthog/core");
var utils_1 = require("./utils");
var request_utils_1 = require("./utils/request-utils");
var event_utils_1 = require("./utils/event-utils");
var DEFAULT_FLUSH_INTERVAL = 5000;
var logger = (0, logger_1.createLogger)('[Heatmaps]');
function elementOrParentPositionMatches(el, matches, breakOnElement) {
    var curEl = el;
    while (curEl && (0, element_utils_1.isElementNode)(curEl) && !(0, element_utils_1.isTag)(curEl, 'body')) {
        if (curEl === breakOnElement) {
            return false;
        }
        if ((0, core_2.includes)(matches, globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.getComputedStyle(curEl).position)) {
            return true;
        }
        curEl = (0, autocapture_utils_1.getParentElement)(curEl);
    }
    return false;
}
function isValidMouseEvent(e) {
    return (0, core_1.isObject)(e) && 'clientX' in e && 'clientY' in e && (0, core_1.isNumber)(e.clientX) && (0, core_1.isNumber)(e.clientY);
}
function shouldPoll(document) {
    return (document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible';
}
var Heatmaps = /** @class */ (function () {
    function Heatmaps(instance) {
        var _a;
        this._enabledServerSide = false;
        this._initialized = false;
        this._flushInterval = null;
        this.instance = instance;
        this._enabledServerSide = !!((_a = this.instance.persistence) === null || _a === void 0 ? void 0 : _a.props[constants_1.HEATMAPS_ENABLED_SERVER_SIDE]);
        this.rageclicks = new rageclick_1.default(instance.config.rageclick);
    }
    Object.defineProperty(Heatmaps.prototype, "_config", {
        get: function () {
            return this.instance.config;
        },
        enumerable: false,
        configurable: true
    });
    Heatmaps.prototype.initialize = function () {
        this.startIfEnabled();
    };
    Object.defineProperty(Heatmaps.prototype, "flushIntervalMilliseconds", {
        get: function () {
            var flushInterval = DEFAULT_FLUSH_INTERVAL;
            if ((0, core_1.isObject)(this._config.capture_heatmaps) && this._config.capture_heatmaps.flush_interval_milliseconds) {
                flushInterval = this._config.capture_heatmaps.flush_interval_milliseconds;
            }
            return flushInterval;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(Heatmaps.prototype, "isEnabled", {
        get: function () {
            if (!(0, core_1.isNullish)(this._config.capture_heatmaps)) {
                return this._config.capture_heatmaps !== false;
            }
            if (!(0, core_1.isNullish)(this._config.enable_heatmaps)) {
                return this._config.enable_heatmaps;
            }
            return this._enabledServerSide;
        },
        enumerable: false,
        configurable: true
    });
    Heatmaps.prototype.startIfEnabled = function () {
        var _a;
        if (this.isEnabled) {
            // nested if here since we only want to run the else
            // if this.enabled === false
            // not if this method is called more than once
            if (this._initialized) {
                return;
            }
            logger.info('starting...');
            this._setupListeners();
            this._onVisibilityChange();
        }
        else {
            clearInterval((_a = this._flushInterval) !== null && _a !== void 0 ? _a : undefined);
            this._removeListeners();
            this.getAndClearBuffer();
        }
    };
    Heatmaps.prototype.onRemoteConfig = function (response) {
        var _a;
        if (!('heatmaps' in response)) {
            return;
        }
        var optIn = !!response['heatmaps'];
        if (this.instance.persistence) {
            this.instance.persistence.register((_a = {},
                _a[constants_1.HEATMAPS_ENABLED_SERVER_SIDE] = optIn,
                _a));
        }
        // store this in-memory in case persistence is disabled
        this._enabledServerSide = optIn;
        this.startIfEnabled();
    };
    Heatmaps.prototype.getAndClearBuffer = function () {
        var buffer = this._buffer;
        this._buffer = undefined;
        return buffer;
    };
    Heatmaps.prototype._onDeadClick = function (click) {
        this._onClick(click.originalEvent, 'deadclick');
    };
    Heatmaps.prototype._onVisibilityChange = function () {
        // always clear the interval just in case
        if (this._flushInterval) {
            clearInterval(this._flushInterval);
        }
        this._flushInterval = shouldPoll(globals_1.document)
            ? setInterval(this._flush.bind(this), this.flushIntervalMilliseconds)
            : null;
    };
    Heatmaps.prototype._setupListeners = function () {
        var _this = this;
        if (!globals_1.window || !globals_1.document) {
            return;
        }
        this._flushHandler = this._flush.bind(this);
        (0, utils_1.addEventListener)(globals_1.window, constants_1.DOM_EVENT_BEFOREUNLOAD, this._flushHandler);
        this._onClickHandler = function (e) { return _this._onClick((e || (globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.event))); };
        (0, utils_1.addEventListener)(globals_1.document, 'click', this._onClickHandler, { capture: true });
        this._onMouseMoveHandler = function (e) { return _this._onMouseMove((e || (globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.event))); };
        (0, utils_1.addEventListener)(globals_1.document, 'mousemove', this._onMouseMoveHandler, { capture: true });
        this._deadClicksCapture = new dead_clicks_autocapture_1.DeadClicksAutocapture(this.instance, dead_clicks_autocapture_1.isDeadClicksEnabledForHeatmaps, this._onDeadClick.bind(this));
        this._deadClicksCapture.startIfEnabledOrStop();
        this._onVisibilityChange_handler = this._onVisibilityChange.bind(this);
        (0, utils_1.addEventListener)(globals_1.document, constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange_handler);
        this._initialized = true;
    };
    Heatmaps.prototype._removeListeners = function () {
        var _a;
        if (!globals_1.window || !globals_1.document) {
            return;
        }
        if (this._flushHandler) {
            globals_1.window.removeEventListener(constants_1.DOM_EVENT_BEFOREUNLOAD, this._flushHandler);
        }
        if (this._onClickHandler) {
            globals_1.document.removeEventListener('click', this._onClickHandler, { capture: true });
        }
        if (this._onMouseMoveHandler) {
            globals_1.document.removeEventListener('mousemove', this._onMouseMoveHandler, { capture: true });
        }
        if (this._onVisibilityChange_handler) {
            globals_1.document.removeEventListener(constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange_handler);
        }
        clearTimeout(this._mouseMoveTimeout);
        (_a = this._deadClicksCapture) === null || _a === void 0 ? void 0 : _a.stop();
        this._initialized = false;
    };
    Heatmaps.prototype._getProperties = function (e, type) {
        // We need to know if the target element is fixed or not
        // If fixed then we won't account for scrolling
        // If not then we will account for scrolling
        var scrollY = this.instance.scrollManager.scrollY();
        var scrollX = this.instance.scrollManager.scrollX();
        var scrollElement = this.instance.scrollManager.scrollElement();
        var isFixedOrSticky = elementOrParentPositionMatches((0, autocapture_utils_1.getEventTarget)(e), ['fixed', 'sticky'], scrollElement);
        return {
            x: e.clientX + (isFixedOrSticky ? 0 : scrollX),
            y: e.clientY + (isFixedOrSticky ? 0 : scrollY),
            target_fixed: isFixedOrSticky,
            type: type,
        };
    };
    Heatmaps.prototype._onClick = function (e, type) {
        var _a;
        if (type === void 0) { type = 'click'; }
        if ((0, element_utils_1.isElementInToolbar)(e.target) || !isValidMouseEvent(e)) {
            return;
        }
        var properties = this._getProperties(e, type);
        if (((_a = this.rageclicks) === null || _a === void 0 ? void 0 : _a.isRageClick(e.clientX, e.clientY, new Date().getTime())) &&
            (0, autocapture_utils_1.shouldCaptureRageclick)((0, autocapture_utils_1.getEventTarget)(e), this.instance.config.rageclick)) {
            this._capture(__assign(__assign({}, properties), { type: 'rageclick' }));
        }
        this._capture(properties);
    };
    Heatmaps.prototype._onMouseMove = function (e) {
        var _this = this;
        if ((0, element_utils_1.isElementInToolbar)(e.target) || !isValidMouseEvent(e)) {
            return;
        }
        clearTimeout(this._mouseMoveTimeout);
        this._mouseMoveTimeout = setTimeout(function () {
            _this._capture(_this._getProperties(e, 'mousemove'));
        }, 500);
    };
    Heatmaps.prototype._capture = function (properties) {
        if (!globals_1.window) {
            return;
        }
        var href = this._config.disable_capture_url_hashes ? (0, core_1.stripUrlHash)(globals_1.window.location.href) : globals_1.window.location.href;
        // mask url query params
        var maskPersonalDataProperties = this._config.mask_personal_data_properties;
        var customPersonalDataProperties = this._config.custom_personal_data_properties;
        var paramsToMask = maskPersonalDataProperties
            ? __spreadArray(__spreadArray([], __read(event_utils_1.PERSONAL_DATA_CAMPAIGN_PARAMS), false), __read((customPersonalDataProperties || [])), false) : [];
        var url = (0, request_utils_1.maskQueryParams)(href, paramsToMask, event_utils_1.MASKED);
        this._buffer = this._buffer || {};
        if (!this._buffer[url]) {
            this._buffer[url] = [];
        }
        this._buffer[url].push(properties);
    };
    Heatmaps.prototype._flush = function () {
        if (!this._buffer || (0, core_1.isEmptyObject)(this._buffer)) {
            return;
        }
        this.instance.capture('$$heatmap', {
            $heatmap_data: this.getAndClearBuffer(),
        });
    };
    return Heatmaps;
}());
exports.Heatmaps = Heatmaps;
//# sourceMappingURL=heatmaps.js.map