"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UserActivityTracker = exports.UserActivityTrackerConfig = exports.UserActivitySet = void 0;
/*
Copyright 2021 The Matrix.org Foundation C.I.C.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const logging = __importStar(require("./logging"));
const log = logging.get("UserActTracker");
// eslint-disable-next-line @typescript-eslint/no-namespace,no-redeclare
var UserActivitySet;
(function (UserActivitySet) {
    UserActivitySet.DEFAULT = {
        users: {}
    };
})(UserActivitySet = exports.UserActivitySet || (exports.UserActivitySet = {}));
// eslint-disable-next-line @typescript-eslint/no-namespace,no-redeclare
var UserActivityTrackerConfig;
(function (UserActivityTrackerConfig) {
    UserActivityTrackerConfig.DEFAULT = {
        inactiveAfterDays: 31,
        minUserActiveDays: 3,
    };
})(UserActivityTrackerConfig = exports.UserActivityTrackerConfig || (exports.UserActivityTrackerConfig = {}));
const ONE_DAY = 24 * 60 * 60 * 1000;
class UserActivityTracker {
    constructor(config, dataSet, onChanges) {
        this.config = config;
        this.dataSet = dataSet;
        this.onChanges = onChanges;
    }
    updateUserActivity(userId, metadata, dateOverride) {
        let userObject = this.dataSet.users[userId];
        if (!userObject) {
            userObject = {
                ts: [],
                metadata: {},
            };
        }
        // Only store it if there are actual keys.
        userObject.metadata = { ...userObject.metadata, ...metadata };
        const date = dateOverride || new Date();
        /** @var newTs Timestamp in seconds of the current UTC day at 12 AM UTC. */
        const newTs = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0, 0) / 1000;
        if (!userObject.ts.includes(newTs)) {
            // Always insert at the start.
            userObject.ts.unshift(newTs);
            // Slice after 31 days
            userObject.ts = userObject.ts.sort((a, b) => b - a).slice(0, 31);
        }
        if (!userObject.metadata.active) {
            /** @var activeSince A unix timestamp in seconds since when the user was active. */
            const activeSince = (date.getTime() - (this.config.minUserActiveDays * ONE_DAY)) / 1000;
            const active = userObject.ts.filter((ts) => ts >= activeSince).length >= this.config.minUserActiveDays;
            if (active) {
                userObject.metadata.active = true;
            }
        }
        this.dataSet.users[userId] = userObject;
        setImmediate(() => {
            var _a;
            log.debug("Notifying the listener of RMAU changes");
            (_a = this.onChanges) === null || _a === void 0 ? void 0 : _a.call(this, {
                changed: [userId],
                dataSet: this.dataSet,
                activeUsers: this.countActiveUsers().allUsers,
            });
        });
    }
    countActiveUsers(dateNow) {
        var _a;
        let allUsers = 0;
        let privateUsers = 0;
        const activeSince = (((dateNow === null || dateNow === void 0 ? void 0 : dateNow.getTime()) || Date.now()) - this.config.inactiveAfterDays * ONE_DAY) / 1000;
        for (const user of Object.values(this.dataSet.users)) {
            if (!user.metadata.active) {
                continue;
            }
            const tsAfterSince = user.ts.filter((ts) => ts >= activeSince);
            if (tsAfterSince.length > 0) {
                allUsers += 1;
                if (((_a = user.metadata) === null || _a === void 0 ? void 0 : _a.private) === true) {
                    privateUsers += 1;
                }
            }
        }
        return { allUsers, privateUsers };
    }
    getUserData(userId) {
        return this.dataSet.users[userId];
    }
}
exports.UserActivityTracker = UserActivityTracker;
//# sourceMappingURL=userActivity.js.map