"use strict";
/*
 *  This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
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.decodeFormValues = exports.encodeFormValues = void 0;
var check_disk_name_basics_1 = require("@cocalc/util/licenses/check-disk-name-basics");
var timecalcs_1 = require("@cocalc/util/stripe/timecalcs");
var consts_1 = require("@cocalc/util/upgrades/consts");
var dedicated_1 = require("@cocalc/util/upgrades/dedicated");
var lodash_1 = require("lodash");
var moment_1 = __importDefault(require("moment"));
var run_limit_1 = require("./run-limit");
// Various support functions for storing quota parameters as a query parameter in the browser URL
function encodeRange(vals) {
    var _a, _b;
    // the list of val is encoded as YYYY-MM-DD and separated by a comma
    // this happens after the "correction" of timestamps in the range selector
    // that's why here is (yet again) some rounding to the start/end of the day.
    var start = vals[0] != null
        ? (_a = (0, moment_1.default)((0, timecalcs_1.roundToMidnight)(vals[0], "start"))) === null || _a === void 0 ? void 0 : _a.format("YYYY-MM-DD")
        : null;
    var end = vals[1] != null
        ? (_b = (0, moment_1.default)((0, timecalcs_1.roundToMidnight)(vals[1], "end"))) === null || _b === void 0 ? void 0 : _b.format("YYYY-MM-DD")
        : null;
    if (start != null && end != null) {
        return [start, end].join("_");
    }
    else {
        return "";
    }
}
// the inverse of encodeRange
function decodeRange(val) {
    var vals = val.split("_");
    var _a = __read([(0, timecalcs_1.startOfDay)(vals[0]), (0, timecalcs_1.endOfDay)(vals[1])], 2), start = _a[0], end = _a[1];
    // if start and end are Date objects, return them
    if (start instanceof Date && end instanceof Date) {
        return [start, end];
    }
    else {
        return [undefined, undefined];
    }
}
function encodeFormValues(router, vals) {
    var query = router.query;
    for (var key in vals) {
        var val = vals[key];
        if (key === "type" || key === "preset")
            continue; // we're already on the right page
        if (val == null) {
            delete query[key];
        }
        else if (key === "range") {
            query[key] = encodeRange(val);
        }
        else {
            query[key] = val;
        }
    }
    router.replace({ query: query }, undefined, { shallow: true, scroll: false });
}
exports.encodeFormValues = encodeFormValues;
function decodeValue(val) {
    if (val === "true")
        return true;
    if (val === "false")
        return false;
    var num = Number(val);
    if (!isNaN(num))
        return num;
    return val;
}
function fixNumVal(val, param) {
    if (typeof val !== "number") {
        return param.dflt;
    }
    else {
        return (0, lodash_1.clamp)(val, param.min, param.max);
    }
}
/** a query looks like this:
 * user=academic&period=monthly&run_limit=1&member=true&uptime=short&cpu=1&ram=2&disk=3
 *
 * NOTE: the support for dedicated disk & vm does not work. the form is too complicated, not no need to support this yet.
 */
function decodeFormValues(router, type) {
    var COMMON_FIELDS = ["user", "period", "range"];
    var FORM_FIELDS = type === "dedicated"
        ? __spreadArray(__spreadArray([], __read(COMMON_FIELDS), false), [
            "disk-size_gb",
            "disk-name",
            "disk-speed",
            "vm-machine",
        ], false) : __spreadArray(__spreadArray([], __read(COMMON_FIELDS), false), [
        "run_limit",
        "member",
        "uptime",
        "cpu",
        "ram",
        "disk",
    ], false);
    var P = type === "boost" ? consts_1.BOOST : consts_1.REGULAR;
    var data = {};
    for (var key in router.query) {
        var val = router.query[key];
        if (!FORM_FIELDS.includes(key))
            continue;
        if (typeof val !== "string")
            continue;
        data[key] = key === "range" ? decodeRange(val) : decodeValue(val);
    }
    // we also have to sanitize the values
    for (var key in data) {
        var val = data[key];
        switch (key) {
            case "user":
                if (!["academic", "commercial"].includes(val)) {
                    data[key] = "academic";
                }
                break;
            case "period":
                if (!["monthly", "yearly", "range"].includes(val)) {
                    data[key] = "monthly";
                }
                break;
            case "range":
                // check that val is an array of length 2 and both entries are Date objects
                if (!Array.isArray(val) || val.length !== 2 || !val.every(lodash_1.isDate)) {
                    data[key] = [undefined, undefined];
                }
                break;
            case "run_limit":
                // check that val is a number and in the range of 1 to 1000
                if (typeof val !== "number" || val < 1 || val > run_limit_1.MAX_ALLOWED_RUN_LIMIT) {
                    data[key] = 1;
                }
                break;
            case "member":
                if (typeof val !== "boolean") {
                    data[key] = true;
                }
                break;
            case "uptime":
                if (!["short", "medium", "day", "always_running"].includes(val)) {
                    data[key] = "short";
                }
                break;
            case "cpu":
                data[key] = fixNumVal(val, P.cpu);
                break;
            case "ram":
                data[key] = fixNumVal(val, P.ram);
                break;
            case "disk":
                data[key] = fixNumVal(val, P.disk);
                break;
            case "disk-size_gb":
                if (typeof val !== "number" || !dedicated_1.DEDICATED_DISK_SIZES.includes(val)) {
                    data[key] = dedicated_1.DEFAULT_DEDICATED_DISK_SIZE;
                }
                break;
            case "disk-name":
                try {
                    (0, check_disk_name_basics_1.testDedicatedDiskNameBasic)(val);
                }
                catch (_a) {
                    data[key] = "";
                }
                break;
            case "disk-speed":
                if (!dedicated_1.DEDICATED_DISK_SPEEDS.includes(val)) {
                    data[key] = dedicated_1.DEFAULT_DEDICATED_DISK_SPEED;
                }
                break;
            case "vm-machine":
                if (dedicated_1.PRICES.vms[val] == null) {
                    data[key] = dedicated_1.DEFAULT_DEDICATED_VM_MACHINE;
                }
                break;
            default:
                console.log("decodingFormValues: unknown key '".concat(key, "'"));
                delete data[key];
        }
    }
    // hosting quality vs. uptime restriction:
    if (["always_running", "day"].includes(data["uptime"])) {
        data["member"] = true;
    }
    if (type === "dedicated") {
        data["type"] = data["vm-machine"] != null ? "vm" : null;
        // if any key in data starts with "disk-" then set data["type"] to "disk"
        if (data["type"] == null) {
            for (var key in data) {
                if (key.startsWith("disk-")) {
                    data["type"] = "disk";
                    break;
                }
            }
        }
        if (data["type"] === "disk") {
            data["period"] = "monthly";
        }
        if (data["type"] === "vm") {
            data["period"] = "range";
        }
    }
    return data;
}
exports.decodeFormValues = decodeFormValues;
//# sourceMappingURL=quota-query-params.js.map