"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
const { Client, utils } = require("@devlego/backend-core/redis");
const { getGlobalIDFromUserMetadataID } = require("../db/utils");
const APP_DEV_LOCK_SECONDS = 600;
const AUTOMATION_TEST_FLAG_SECONDS = 60;
let devAppClient, debounceClient, flagClient;
// we init this as we want to keep the connection open all the time
// reduces the performance hit
exports.init = () => __awaiter(void 0, void 0, void 0, function* () {
    devAppClient = new Client(utils.Databases.DEV_LOCKS);
    debounceClient = new Client(utils.Databases.DEBOUNCE);
    flagClient = new Client(utils.Databases.FLAGS);
    yield devAppClient.init();
    yield debounceClient.init();
    yield flagClient.init();
});
exports.shutdown = () => __awaiter(void 0, void 0, void 0, function* () {
    if (devAppClient)
        yield devAppClient.finish();
    if (debounceClient)
        yield debounceClient.finish();
    if (flagClient)
        yield flagClient.finish();
});
exports.doesUserHaveLock = (devAppId, user) => __awaiter(void 0, void 0, void 0, function* () {
    const value = yield devAppClient.get(devAppId);
    if (!value) {
        return true;
    }
    // make sure both IDs are global
    const expected = getGlobalIDFromUserMetadataID(value._id);
    const userId = getGlobalIDFromUserMetadataID(user._id);
    return expected === userId;
});
exports.getAllLocks = () => __awaiter(void 0, void 0, void 0, function* () {
    const locks = yield devAppClient.scan();
    return locks.map(lock => ({
        appId: lock.key,
        user: lock.value,
    }));
});
exports.updateLock = (devAppId, user) => __awaiter(void 0, void 0, void 0, function* () {
    // make sure always global user ID
    const globalId = getGlobalIDFromUserMetadataID(user._id);
    const inputUser = Object.assign(Object.assign({}, user), { userId: globalId, _id: globalId, lockedAt: new Date().getTime() });
    yield devAppClient.store(devAppId, inputUser, APP_DEV_LOCK_SECONDS);
});
exports.clearLock = (devAppId, user) => __awaiter(void 0, void 0, void 0, function* () {
    const value = yield devAppClient.get(devAppId);
    if (!value) {
        return;
    }
    const userId = getGlobalIDFromUserMetadataID(user._id);
    if (value._id !== userId) {
        throw "User does not hold lock, cannot clear it.";
    }
    yield devAppClient.delete(devAppId);
});
exports.checkDebounce = (id) => __awaiter(void 0, void 0, void 0, function* () {
    return debounceClient.get(id);
});
exports.setDebounce = (id, seconds) => __awaiter(void 0, void 0, void 0, function* () {
    yield debounceClient.store(id, "debouncing", seconds);
});
exports.setTestFlag = (id) => __awaiter(void 0, void 0, void 0, function* () {
    yield flagClient.store(id, { testing: true }, AUTOMATION_TEST_FLAG_SECONDS);
});
exports.checkTestFlag = (id) => __awaiter(void 0, void 0, void 0, function* () {
    const flag = yield flagClient.get(id);
    return !!(flag && flag.testing);
});
exports.clearTestFlag = (id) => __awaiter(void 0, void 0, void 0, function* () {
    yield devAppClient.delete(id);
});
