import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
import { useCallback, useEffect, useState, } from 'react';
import { CameraIcon } from '@datalayer/icons-react';
import { ActionList, ActionMenu, Flash, FormControl, Select, Spinner, } from '@primer/react';
import { Dialog } from '@primer/react/experimental';
import { Box } from '@datalayer/primer-addons';
import { useToast } from '../../hooks/index.js';
import { createRuntimeSnapshot, getRuntimeSnapshots, loadBrowserRuntimeSnapshot, loadRuntimeSnapshot, } from '../../stateful/runtimes/index.js';
import { useRuntimesStore } from '../../state/index.js';
import { createRuntimeSnapshotName } from '../../utils/index.js';
/**
 * Runtime Snapshot menu component.
 */
export function RuntimeSnapshotMenu({ children, connection, podName, multiServiceManager, disabled = false, }) {
    const { addRuntimeSnapshot, runtimesRunUrl, runtimeSnapshots, setRuntimeSnapshots, } = useRuntimesStore();
    const { enqueueToast, trackAsyncTask } = useToast();
    const [openLoadDialog, setOpenLoadDialog] = useState(false);
    const [loadingRuntimeSnapshot, setLoadingRuntimeSnapshot] = useState(false);
    const [takingRuntimeSnapshot, setTakingRuntimeSnapshot] = useState(false);
    const [selection, setSelection] = useState(runtimeSnapshots[0]?.id ?? '');
    const [error, setError] = useState();
    useEffect(() => {
        getRuntimeSnapshots()
            .then(snapshots => {
            setRuntimeSnapshots(snapshots);
            if (!selection && snapshots.length > 0) {
                setSelection(snapshots[0].id);
            }
        })
            .catch(reason => {
            console.error(`Failed to fetch remote kernel snapshots; ${reason}`);
        });
    }, [runtimesRunUrl]);
    const onLoadRuntimeSnapshot = useCallback(() => {
        setError(undefined);
        setOpenLoadDialog(true);
    }, []);
    const onRuntimeSnapshotChanged = useCallback(event => {
        setSelection(event.target.value);
    }, []);
    const onLoadRuntimeSnapshotSubmit = useCallback(async ({ id, connection, podName, }) => {
        if (podName) {
            await loadRuntimeSnapshot({ id: podName, from: id });
            enqueueToast(`Runtime snapshot ${podName} is loaded.`, {
                variant: 'success',
            });
        }
        else if (connection) {
            await loadBrowserRuntimeSnapshot({ connection, id });
            enqueueToast(`Runtime snapshot ${id} is loaded.`, {
                variant: 'success',
            });
        }
    }, []);
    const onTakeRuntimeSnapshot = useCallback(async () => {
        try {
            setTakingRuntimeSnapshot(true);
            let snapshot;
            let task;
            let ref = '';
            let snapshotName = '';
            if (podName && multiServiceManager?.remote) {
                snapshotName = createRuntimeSnapshotName('cloud');
                task = multiServiceManager.remote.runtimesManager.snapshotRuntime({
                    podName,
                    name: snapshotName,
                    description: snapshotName,
                    stop: false,
                });
                ref = podName.split('-', 2).reverse()[0];
                task.then(s => {
                    snapshot = s;
                });
            }
            else if (connection && multiServiceManager?.browser) {
                const model = connection.model;
                ref = model.id;
                snapshotName = createRuntimeSnapshotName('browser');
                let isPending = true;
                task = createRuntimeSnapshot({
                    connection: multiServiceManager.browser.kernels.connectTo({
                        model,
                    }),
                    metadata: { filename: `${snapshotName}.data` },
                    onUploadProgress: () => {
                        if (isPending) {
                            isPending = false;
                            // Get the kernel snapshot uid.
                            getRuntimeSnapshots().then(snapshots => {
                                snapshot = snapshots.find(s => s.name === snapshotName);
                            });
                        }
                    },
                });
            }
            if (task) {
                trackAsyncTask(task, {
                    error: {
                        message: (reason, data) => {
                            const msg = reason === 'Empty snapshot'
                                ? `Runtime ${ref} will not be snapshotted as it does not contain any serializable state.`
                                : `Failed to snapshot runtime ${ref} - ${reason}`;
                            return msg;
                        },
                    },
                    pending: { message: `Taking a snapshot of runtime ${ref}…` },
                    success: {
                        message: () => `Runtime ${ref} successfully snapshotted as ${snapshotName}.`,
                    },
                });
                await task;
                if (snapshot) {
                    addRuntimeSnapshot(snapshot);
                }
            }
        }
        finally {
            setTakingRuntimeSnapshot(false);
        }
    }, [connection, podName, multiServiceManager]);
    return (_jsxs(_Fragment, { children: [_jsxs(ActionMenu, { children: [_jsx(ActionMenu.Button, { leadingVisual: CameraIcon, variant: "invisible", size: "small", disabled: loadingRuntimeSnapshot || takingRuntimeSnapshot || disabled, children: children }), _jsx(ActionMenu.Overlay, { children: _jsxs(ActionList, { children: [_jsx(ActionList.Item, { onSelect: onLoadRuntimeSnapshot, disabled: loadingRuntimeSnapshot || runtimeSnapshots.length === 0, children: "Load a runtime snapshot\u2026" }), _jsx(ActionList.Item, { onSelect: onTakeRuntimeSnapshot, disabled: takingRuntimeSnapshot, children: "Take a runtime snapshot" })] }) })] }), openLoadDialog && (_jsx(Dialog, { title: _jsx("span", { style: { color: 'var(--fgColor-default)' }, children: "Choose a runtime snapshot to load" }), onClose: () => {
                    setOpenLoadDialog(false);
                }, footerButtons: [
                    {
                        buttonType: 'default',
                        content: 'Cancel',
                        onClick: event => {
                            if (!event.defaultPrevented) {
                                event.preventDefault();
                                setOpenLoadDialog(false);
                            }
                        },
                    },
                    {
                        buttonType: 'primary',
                        content: loadingRuntimeSnapshot ? (_jsx(Spinner, { size: "small" })) : ('Load'),
                        disabled: loadingRuntimeSnapshot,
                        onClick: async (event) => {
                            if (!event.defaultPrevented) {
                                event.preventDefault();
                                setLoadingRuntimeSnapshot(true);
                                try {
                                    setError(undefined);
                                    const snapshot = runtimeSnapshots.find(s => s.id === selection);
                                    if (snapshot && (connection || podName)) {
                                        await onLoadRuntimeSnapshotSubmit({
                                            connection,
                                            id: snapshot.id,
                                            podName,
                                        });
                                    }
                                    else {
                                        setError('No runtime snapshot found.');
                                    }
                                }
                                finally {
                                    setLoadingRuntimeSnapshot(false);
                                    setOpenLoadDialog(false);
                                }
                            }
                        },
                        autoFocus: true,
                    },
                ], children: _jsxs(Box, { as: "form", children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Snapshot" }), _jsx(Select, { name: "snapshot", value: selection, onChange: onRuntimeSnapshotChanged, block: true, children: runtimeSnapshots.map(s => (_jsx(Select.Option, { value: s.id, children: s.name ? `${s.name} (${s.id})` : s.id }, s.id))) })] }), error && _jsx(Flash, { variant: "danger", children: error })] }) }))] }));
}
