import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } 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 { ActionList, FormControl, ToggleSwitch, Tooltip, IconButton, } from '@primer/react';
import { Box } from '@datalayer/primer-addons';
import { AlertIcon } from '@primer/octicons-react';
import { JSONExt } from '@lumino/coreutils';
import { KernelExecutor } from '@datalayer/jupyter-react';
import { RuntimeSnippetsFacade } from '../../stateful/jupyter/index.js';
import { ExternalTokenSilentLogin } from '../../components/iam/index.js';
import { useCoreStore, useIAMStore } from '../../state/index.js';
import { RuntimeReservationControl, MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES, } from './RuntimeReservationControl.js';
import { RuntimeVariables } from './RuntimeVariables.js';
import { RuntimePickerBase } from './RuntimePickerBase.js';
/**
 * Runtime Picker components for a Notebook.
 */
export function RuntimePickerNotebook(props) {
    const { multiServiceManager, sessionContext, setValue, translator } = props;
    const { configuration } = useCoreStore();
    const { credits, refreshCredits, token } = useIAMStore();
    const [selectedRuntimeDesc, setSelectedRuntimeDesc] = useState();
    const [timeLimit, setTimeLimit] = useState(Math.min(credits?.available ?? 0, 10));
    const [userStorage, setUserStorage] = useState(false);
    const [canTransferFrom, setTransferFrom] = useState(false);
    const [canTransferTo, setTransferTo] = useState(false);
    const [transferVariables, setTransferVariables] = useState(false);
    const [hasLoadedVariables, setHasLoadedVariables] = useState(false);
    const [kernelVariables, setRuntimeVariables] = useState();
    const [toTransfer, setToTransfer] = useState([]);
    useEffect(() => {
        refreshCredits();
    }, []);
    useEffect(() => {
        const specs = sessionContext.specsManager.specs?.kernelspecs;
        if (sessionContext.session?.kernel?.name && specs) {
            const spec = Object.values(specs).find(spec => spec?.name === sessionContext.session.kernel.name);
            if (spec) {
                setSelectedRuntimeDesc({
                    name: spec.name,
                    kernelId: sessionContext.session.kernel.id,
                    location: sessionContext.location,
                    language: spec.language,
                    displayName: sessionContext.kernelDisplayName,
                });
                setTransferFrom(RuntimeSnippetsFacade.supports(spec.language));
            }
        }
    }, [sessionContext]);
    const listRuntimeVariables = useCallback(async () => {
        if (hasLoadedVariables) {
            return Promise.resolve();
        }
        setHasLoadedVariables(true);
        const connection = sessionContext.session.kernel;
        const spec = sessionContext.specsManager.specs.kernelspecs[connection.model.name];
        const snippets = new RuntimeSnippetsFacade(spec.language);
        const outputs = await new KernelExecutor({ connection }).execute(snippets.listVariables());
        const content = outputs.get(0).data['text/plain'];
        if (content) {
            setRuntimeVariables(JSON.parse(
            // We need to remove the quotes prior to parsing.
            content.slice(1, content.length - 1)));
            if (toTransfer.length) {
                const candidates = Object.keys(kernelVariables ?? {});
                setToTransfer(toTransfer.filter(n => candidates.includes(n)));
            }
            else {
                // By default select all variables.
                setToTransfer(Object.keys(kernelVariables ?? {}));
            }
        }
        else {
            setRuntimeVariables({});
        }
    }, [hasLoadedVariables, kernelVariables, toTransfer]);
    const setSelectedVariables = useCallback((l) => {
        if (!JSONExt.deepEqual(toTransfer, l)) {
            setToTransfer(l);
        }
    }, [toTransfer]);
    const setTransferVariable = useCallback((value) => {
        if (transferVariables !== value) {
            if (value) {
                listRuntimeVariables().catch(error => {
                    console.error('Failed to list the runtime variable', error);
                    setHasLoadedVariables(false);
                });
            }
            setTransferVariables(value);
        }
    }, [transferVariables]);
    const setRuntimeDesc = useCallback((runtimeDesc) => {
        if (!runtimeDesc) {
            if (selectedRuntimeDesc) {
                setSelectedRuntimeDesc(undefined);
                setTransferTo(false);
            }
            return;
        }
        if (selectedRuntimeDesc?.displayName !== runtimeDesc.displayName ||
            selectedRuntimeDesc?.kernelId !== runtimeDesc.kernelId) {
            setSelectedRuntimeDesc({ ...runtimeDesc });
            setTransferTo(RuntimeSnippetsFacade.supports(runtimeDesc.language));
        }
    }, [selectedRuntimeDesc]);
    const handleUserStorageChange = useCallback((e) => {
        e.preventDefault();
        setUserStorage(!userStorage);
    }, [userStorage]);
    useEffect(() => {
        const creditsLimit = selectedRuntimeDesc?.location === 'remote' &&
            selectedRuntimeDesc.burningRate
            ? Math.min(timeLimit, MAXIMAL_RUNTIME_TIME_RESERVATION_MINUTES) *
                selectedRuntimeDesc.burningRate *
                60
            : undefined;
        setValue(creditsLimit !== 0
            ? {
                runtime: selectedRuntimeDesc
                    ? {
                        environmentName: ['browser', 'remote'].includes(selectedRuntimeDesc.location)
                            ? `${selectedRuntimeDesc.location}-${selectedRuntimeDesc.name}`
                            : selectedRuntimeDesc.name,
                        id: selectedRuntimeDesc.kernelId,
                        creditsLimit,
                        capabilities: userStorage ? ['user_storage'] : undefined,
                    }
                    : null,
                selectedVariables: toTransfer,
            }
            : new Error('Credits limit must be strictly positive.'));
    }, [selectedRuntimeDesc, userStorage, toTransfer, timeLimit]);
    const { kernelPreference: { canStart }, } = sessionContext;
    const max = Math.floor((credits?.available ?? 0) / (selectedRuntimeDesc?.burningRate ?? -1) / 60.0);
    const outOfCredits = !credits?.available || max < Number.EPSILON;
    return (_jsxs(Box, { as: "form", className: "dla-Runtimes-picker", children: [_jsx(Box, { sx: { padding: 'var(--stack-padding-condensed) 0' }, children: _jsx(RuntimePickerBase, { display: "radio", disabled: canStart === false, preference: {
                        id: sessionContext.session?.id,
                        kernelDisplayName: sessionContext.kernelPreference.shouldStart
                            ? sessionContext.kernelDisplayName
                            : undefined,
                    }, sessionContext: sessionContext, multiServiceManager: multiServiceManager, translator: translator, runtimeDesc: selectedRuntimeDesc, setRuntimeDesc: setRuntimeDesc, postActions: token || !props.logIn ? (
                    /*
                  <Button
                    variant="default"
                    onClick={e => {
                      e.preventDefault();
                      commands.execute(CommandIDs.launchRemoteRuntime);
                      close();
                    }}
                  >
                    Launch a New Runtime
                  </Button>
                  */
                    _jsx(_Fragment, {})) : (_jsx(ActionList.Item, { onSelect: props.logIn, title: 'Connect to Runtime provider.', children: _jsx(ExternalTokenSilentLogin, { message: "Connect to the Runtime provider" }) })) }) }), !selectedRuntimeDesc?.kernelId &&
                selectedRuntimeDesc?.location === 'remote' && (_jsxs(_Fragment, { children: [_jsx(RuntimeReservationControl, { disabled: outOfCredits || selectedRuntimeDesc?.location !== 'remote', label: 'Time reservation', max: max < 0 ? 1 : max, time: timeLimit, onTimeChange: setTimeLimit, error: outOfCredits && max >= 0
                            ? 'You must add credits to your account.'
                            : timeLimit === 0
                                ? 'You must set a time limit.'
                                : undefined, burningRate: selectedRuntimeDesc.burningRate }), !configuration.whiteLabel && (_jsxs(FormControl, { disabled: !!selectedRuntimeDesc?.kernelId ||
                            selectedRuntimeDesc?.location !== 'remote', layout: "horizontal", children: [_jsxs(FormControl.Label, { id: "user-storage-picker-label", children: ["User storage", _jsx(Tooltip, { text: "The runtime will be slower to start.", direction: "e", style: { marginLeft: 3 }, children: _jsx(IconButton, { icon: AlertIcon, "aria-label": "", variant: "invisible" }) })] }), _jsx(ToggleSwitch, { disabled: !!selectedRuntimeDesc?.kernelId ||
                                    selectedRuntimeDesc?.location !== 'remote', checked: userStorage, size: "small", onClick: handleUserStorageChange, "aria-labelledby": "user-storage-picker-label" })] }))] })), canTransferFrom && canTransferTo && (_jsx(RuntimeVariables, { selectedVariables: toTransfer, setSelectVariable: setSelectedVariables, transferVariables: transferVariables, setTransferVariable: setTransferVariable, kernelVariables: kernelVariables, translator: translator }))] }));
}
export default RuntimePickerNotebook;
