"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const lodash_1 = require("lodash");
const antd_1 = require("antd");
const mounted_1 = __importDefault(require("lib/hooks/mounted"));
const loading_1 = __importDefault(require("components/share/loading"));
const post_1 = __importDefault(require("lib/api/post"));
const icon_1 = require("@cocalc/frontend/components/icon");
const schema_1 = require("@cocalc/util/schema");
const misc_1 = require("@cocalc/util/misc");
const DEBOUNCE_MS = 1500;
function SaveButton({ disabled, edited, original, setOriginal, table, style, onSave, isValid, debounce_ms, }) {
    if (debounce_ms == null)
        debounce_ms = DEBOUNCE_MS;
    const [saving, setSaving] = (0, react_1.useState)(false);
    const [error, setError] = (0, react_1.useState)("");
    // Tricky hooks: We have to store the state in a ref as well so that
    // we can use it in the save function, since that function
    // is memoized and called from a debounced function.
    const saveRef = (0, react_1.useRef)({ edited, original, table });
    saveRef.current = { edited, original, table };
    const isMounted = (0, mounted_1.default)();
    const save = (0, react_1.useMemo)(() => {
        return async () => {
            const { edited, original, table } = saveRef.current;
            let changes = false;
            const e = {};
            for (const field in edited) {
                if (!(0, lodash_1.isEqual)(original[field], edited[field])) {
                    e[field] = (0, lodash_1.cloneDeep)(edited[field]);
                    changes = true;
                }
            }
            if (!changes) {
                // no changes to save.
                return false;
            }
            for (const field of preserveFields(table)) {
                e[field] = (0, lodash_1.cloneDeep)(edited[field]);
            }
            const query = { [table]: e };
            if (isMounted.current) {
                setSaving(true);
                setError("");
            }
            let result;
            try {
                // Note -- we definitely do want to do the save
                // itself, even if the component is already unmounted,
                // so we don't loose changes.
                result = await (0, post_1.default)("/user-query", { query });
            }
            catch (err) {
                if (!isMounted.current)
                    return;
                setError(err.message);
                return false;
            }
            finally {
                if (isMounted.current) {
                    setSaving(false);
                }
            }
            if (!isMounted.current)
                return;
            if (result.error) {
                setError(result.error);
            }
            else {
                setOriginal((0, lodash_1.cloneDeep)(edited));
            }
            return true; // successful save
        };
    }, []);
    async function doSave() {
        const e = (0, lodash_1.cloneDeep)(saveRef.current.edited);
        if (table) {
            const didSave = await save();
            if (!isMounted.current)
                return;
            if (didSave) {
                await onSave?.(e);
            }
            return;
        }
        try {
            await onSave?.(e);
            if (!isMounted.current)
                return;
            setOriginal(e);
            setError("");
        }
        catch (err) {
            setError(err.toString());
        }
    }
    const doSaveDebounced = (0, react_1.useMemo)(() => (0, lodash_1.debounce)(doSave, debounce_ms), [onSave]);
    (0, react_1.useEffect)(() => {
        doSaveDebounced();
        return doSaveDebounced;
    }, [edited]);
    const same = (0, lodash_1.isEqual)(edited, original);
    return ((0, jsx_runtime_1.jsxs)("div", { style: style, children: [(0, jsx_runtime_1.jsx)(antd_1.Button, { type: "primary", disabled: disabled ?? (saving || same || (isValid != null && !isValid(edited))), onClick: doSave, children: (0, jsx_runtime_1.jsxs)(antd_1.Space, { children: [(0, jsx_runtime_1.jsx)(icon_1.Icon, { name: "save" }), saving ? ((0, jsx_runtime_1.jsx)(loading_1.default, { delay: 250, before: "Save", children: "Saving..." })) : ("Save")] }) }), !same && error && ((0, jsx_runtime_1.jsx)(antd_1.Alert, { type: "error", message: error, style: { marginTop: "15px" } }))] }));
}
exports.default = SaveButton;
function preserveFields(table) {
    return (0, misc_1.keys)(schema_1.SCHEMA[table].user_query?.set?.required_fields ?? {});
}
//# sourceMappingURL=save-button.js.map