"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemberHostingAndIdleTimeout = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/*
 *  This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.
 *  License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
 */
const icon_1 = require("@cocalc/frontend/components/icon");
const site_license_1 = require("@cocalc/util/consts/site-license");
const antd_1 = require("antd");
const A_1 = __importDefault(require("components/misc/A"));
const api_1 = __importDefault(require("lib/hooks/api"));
const react_1 = require("react");
const { Text } = antd_1.Typography;
const { Option } = antd_1.Select;
const ManagedLicenses = (props) => {
    const { setConfig } = props;
    const { result, error, call: refresh, calling, } = (0, api_1.default)("licenses/get-managed", undefined, 600);
    const managedLicenses = (0, react_1.useMemo)(() => {
        if (!Array.isArray(result))
            return [];
        const now = Date.now();
        const filtered = result?.filter((l) => {
            // hide expired licenses
            if (l.expires != null && l.expires < now)
                return false;
            if (l.quota?.dedicated_disk != null || l.quota?.dedicated_vm != null) {
                return false;
            }
            return true;
        }) ?? [];
        filtered.sort((a, b) => {
            return (a.activated ?? 0) - (b.activated ?? 0);
        });
        return filtered;
    }, [result]);
    function shortQuotaDescription(run_limit, quota) {
        if (quota == null)
            return ""; // I saw this in production.
        const { cpu, ram, disk, always_running, idle_timeout, member } = quota;
        const up = always_running === true
            ? "always running"
            : idle_timeout != null
                ? (0, site_license_1.displaySiteLicense)(idle_timeout)
                : "idle-timeout unknown";
        const mh = member ? "member hosting" : "no member hosting";
        const res = `${cpu} CPU, ${ram}G RAM, ${disk}G disk`;
        return `${run_limit}x ${res}, ${up}, ${mh}`;
    }
    function renderLicenses() {
        if (managedLicenses == null || managedLicenses.length === 0) {
            return [
                (0, jsx_runtime_1.jsx)(Option, { value: "first", disabled: "true", children: calling ? "Loading…" : "No licenses found" }, "first"),
            ];
        }
        else {
            const entries = managedLicenses.map((license) => {
                // split the license id at "-" and take the last part
                const shortID = license.id.split("-").pop();
                const quota = shortQuotaDescription(license.run_limit, license.quota);
                return ((0, jsx_runtime_1.jsxs)(Option, { value: license.id, children: [license.title ?? "No title", " ", (0, jsx_runtime_1.jsxs)(Text, { type: "secondary", children: ["(", shortID, ")"] }), ": ", quota] }, license.id));
            });
            entries.unshift((0, jsx_runtime_1.jsx)(Option, { disabled: "true", value: "first", children: "Select a license" }, "first"));
            return entries;
        }
    }
    function onSelection(license_id) {
        const license = managedLicenses.find((l) => l.id === license_id);
        if (license == null)
            return;
        const q = license.quota;
        if (q == null)
            return;
        const uptime = q.always_running === true ? "always_running" : q.idle_timeout;
        setConfig({ member: q.member, uptime });
    }
    if (error) {
        return ((0, jsx_runtime_1.jsx)(antd_1.Alert, { type: "error", message: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("p", { children: ["Unable to retrieve licenses:", " ", (0, jsx_runtime_1.jsx)(antd_1.Button, { type: "link", onClick: () => refresh(undefined, undefined, 0), children: "try again" })] }), (0, jsx_runtime_1.jsx)("pre", { style: { whiteSpace: "pre-wrap" }, children: error })] }) }));
    }
    else {
        return ((0, jsx_runtime_1.jsx)(antd_1.Select, { loading: calling, defaultValue: "first", suffixIcon: (0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "reload", onClick: () => refresh() }), onChange: onSelection, children: renderLicenses() }));
    }
};
function MemberHostingAndIdleTimeout(props) {
    const { shadowMember, setShadowMember, form, showExplanations, onChange, setPresetAdjusted, boost = false, disabled = false, } = props;
    function setConfig({ member, uptime }) {
        setUptime(uptime);
        setMemberHosting(member);
    }
    function memberExplanation() {
        if (!showExplanations)
            return;
        if (boost) {
            return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "The state of Member Hosting must match the corresponding Site License you want to boost." }));
        }
        else {
            return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Member hosting significantly reduces competition for resources, and we prioritize", " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "support/new", external: true, children: "support requests" }), " ", "much higher. All licensed projects, with or without member hosting, have network access, so they can connect to the network to clone Git repositories, download data files and install software.", (0, site_license_1.requiresMemberhosting)(form.getFieldValue("uptime")) && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)(Text, { italic: true, type: "secondary", children: "Note: this level of idle timeout requires member hosting." })] })), (0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)(Text, { italic: true, type: "secondary", children: "Please be aware: licenses of different member hosting service levels cannot be combined!" })] }));
        }
    }
    function idleTimeoutExplanation() {
        if (!showExplanations)
            return;
        if (boost) {
            return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "The Idle timeout of this Boost license must match the corresponding Site License you want to boost." }));
        }
        const uptime = form.getFieldValue("uptime");
        const bottom = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)(Text, { italic: true, type: "secondary", children: "Please be aware: licenses with different idle timeouts cannot be combined!" })] }));
        const main = (function () {
            if (uptime === "always_running") {
                return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Text, { strong: true, type: "secondary", children: "Keep projects running:" }), " ", "Once started your project stays running, so you can run very long computations and also never have to wait for your project to start. This effectively disables", " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "https://doc.cocalc.com/howto/software-development.html#idle-timeout", children: "idle timeout" }), ", since your project will restart automatically if it stops. See", " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "https://doc.cocalc.com/project-init.html", children: "project init scripts" }), ". (Note: this is NOT guaranteed 100% uptime, since projects may sometimes restart for security and maintenance reasons.)"] }));
            }
            else {
                return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Projects stop automatically if they are not actively used. Increasing", " ", (0, jsx_runtime_1.jsx)(A_1.default, { href: "https://doc.cocalc.com/howto/software-development.html#idle-timeout", children: "idle timeout" }), " ", "will allow you to run longer calculations without you having to be active while they run. However, this is not 100% guaranteed, because projects may still restart due to maintenance or security reasons."] }));
            }
        })();
        return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [main, bottom] }));
    }
    function uptimeOptions() {
        const ret = [];
        for (const [key, it] of Object.entries(site_license_1.LicenseIdleTimeouts)) {
            ret.push((0, jsx_runtime_1.jsx)(antd_1.Radio.Button, { value: key, children: it.label }, key));
        }
        ret.push((0, jsx_runtime_1.jsx)(antd_1.Radio.Button, { value: "always_running", children: "Always running" }, "always_running"));
        return ret;
    }
    function boostAssist() {
        if (!boost)
            return;
        return ((0, jsx_runtime_1.jsxs)(antd_1.Form.Item, { label: "Select license", children: ["Boosts can only boost matching \"Member hosting\" and \"Idle timeout\" licenses. If you are unsure, select one of your licenses:", " ", (0, jsx_runtime_1.jsx)(ManagedLicenses, { setConfig: setConfig })] }));
    }
    function setUptime(uptime) {
        form.setFieldsValue({ uptime });
        setPresetAdjusted?.(true);
        onChange();
    }
    function setMemberHosting(member) {
        form.setFieldsValue({ member });
        setPresetAdjusted?.(true);
        onChange();
    }
    return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(antd_1.Divider, { plain: true, children: [boost ? "Matching" : "", " Hosting quality and Idle timeout"] }), boostAssist(), (0, jsx_runtime_1.jsx)(antd_1.Form.Item, { initialValue: true, label: "Member hosting", name: "member", valuePropName: "checked", dependencies: ["uptime"], rules: [
                    ({ getFieldValue, setFieldsValue }) => ({
                        validator: (_, value) => {
                            // we force member true if the uptime is higher than medium
                            const uptime = getFieldValue("uptime");
                            if ((0, site_license_1.requiresMemberhosting)(uptime)) {
                                if (value !== true) {
                                    setShadowMember(value);
                                    setFieldsValue({ member: true });
                                }
                            }
                            else {
                                // if the user toggles back to a lower idle timeout,
                                // we use shadowMember to restore the previous member value.
                                if (shadowMember != null) {
                                    setFieldsValue({ member: shadowMember });
                                    setShadowMember(null);
                                }
                            }
                        },
                    }),
                ], extra: memberExplanation(), children: (0, jsx_runtime_1.jsx)(antd_1.Checkbox, { disabled: disabled || (0, site_license_1.requiresMemberhosting)(form.getFieldValue("uptime")), onChange: (e) => setMemberHosting(e.target.checked), children: "Run project on a much better host with network access" }) }), (0, jsx_runtime_1.jsx)(antd_1.Form.Item, { initialValue: "short", name: "uptime", label: "Idle timeout", extra: idleTimeoutExplanation(), children: (0, jsx_runtime_1.jsx)(antd_1.Radio.Group, { disabled: disabled, onChange: (e) => setUptime(e.target.value), children: uptimeOptions() }) })] }));
}
exports.MemberHostingAndIdleTimeout = MemberHostingAndIdleTimeout;
//# sourceMappingURL=member-idletime.js.map