"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.KeyframeInspector = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const studio_shared_1 = require("@remotion/studio-shared");
const react_1 = require("react");
const remotion_1 = require("remotion");
const client_id_1 = require("../../helpers/client-id");
const timeline_layout_1 = require("../../helpers/timeline-layout");
const is_menu_item_1 = require("../Menu/is-menu-item");
const InputDragger_1 = require("../NewComposition/InputDragger");
const call_delete_keyframe_1 = require("../Timeline/call-delete-keyframe");
const call_move_keyframe_1 = require("../Timeline/call-move-keyframe");
const get_easing_selection_after_keyframe_delete_1 = require("../Timeline/get-easing-selection-after-keyframe-delete");
const parse_keyframe_field_from_node_path_1 = require("../Timeline/parse-keyframe-field-from-node-path");
const TimelineEffectPropItem_1 = require("../Timeline/TimelineEffectPropItem");
const TimelineSelection_1 = require("../Timeline/TimelineSelection");
const TimelineSequencePropItem_1 = require("../Timeline/TimelineSequencePropItem");
const update_selected_easing_1 = require("../Timeline/update-selected-easing");
const common_1 = require("./common");
const keyframe_inspector_frame_1 = require("./keyframe-inspector-frame");
const KeyframeEasingNavigator_1 = require("./KeyframeEasingNavigator");
const SequenceInspectorHeader_1 = require("./SequenceInspectorHeader");
const styles_1 = require("./styles");
const use_track_for_selection_1 = require("./use-track-for-selection");
const makeMovedKeyframedDragOverride = ({ details, toFrame, }) => {
    if (!(0, studio_shared_1.canMoveKeyframesWithoutCollisions)({
        status: details.propStatus,
        moves: [{ fromFrame: details.sourceFrame, toFrame }],
    })) {
        return null;
    }
    const movedStatus = (0, studio_shared_1.moveKeyframesInPropStatus)({
        status: details.propStatus,
        moves: [{ fromFrame: details.sourceFrame, toFrame }],
    });
    if (movedStatus.status !== 'keyframed') {
        return null;
    }
    return {
        type: 'keyframed',
        status: movedStatus,
    };
};
const removeKeyframeIcon = {
    display: 'block',
    flexShrink: 0,
    height: 13,
    width: 12,
};
const TrashIcon = ({ color }) => {
    return (jsx_runtime_1.jsx("svg", { viewBox: "0 0 448 512", style: removeKeyframeIcon, children: jsx_runtime_1.jsx("path", { fill: color, d: "M136.7 5.9C141.1-7.2 153.3-16 167.1-16l113.9 0c13.8 0 26 8.8 30.4 21.9L320 32 416 32c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 96C14.3 96 0 81.7 0 64S14.3 32 32 32l96 0 8.7-26.1zM32 144l384 0 0 304c0 35.3-28.7 64-64 64L96 512c-35.3 0-64-28.7-64-64l0-304zm88 64c-13.3 0-24 10.7-24 24l0 192c0 13.3 10.7 24 24 24s24-10.7 24-24l0-192c0-13.3-10.7-24-24-24zm104 0c-13.3 0-24 10.7-24 24l0 192c0 13.3 10.7 24 24 24s24-10.7 24-24l0-192c0-13.3-10.7-24-24-24zm104 0c-13.3 0-24 10.7-24 24l0 192c0 13.3 10.7 24 24 24s24-10.7 24-24l0-192c0-13.3-10.7-24-24-24z" }) }));
};
const KeyframeInspector = ({ selection }) => {
    const track = (0, use_track_for_selection_1.useTrackForSelection)(selection);
    const videoConfig = (0, remotion_1.useVideoConfig)();
    const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
    const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
    const { clearDragOverrides, clearEffectDragOverrides, setDragOverrides, setEffectDragOverrides, setPropStatuses, } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
    const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
    const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
    const { selectItems } = (0, TimelineSelection_1.useTimelineSelection)();
    const [draftFrame, setDraftFrame] = (0, react_1.useState)(selection.frame);
    const parentSelection = (0, react_1.useMemo)(() => (0, TimelineSelection_1.getTimelineSelectionFromNodePathInfo)(selection.nodePathInfo), [selection.nodePathInfo]);
    (0, react_1.useEffect)(() => {
        setDraftFrame(selection.frame);
    }, [selection.frame]);
    const details = (0, react_1.useMemo)(() => {
        var _a;
        var _b, _c, _d, _e, _f, _g;
        if (!track || !track.sequence.controls) {
            return null;
        }
        const keyframeField = (0, parse_keyframe_field_from_node_path_1.parseKeyframeFieldFromNodePath)(selection.nodePathInfo.auxiliaryKeys);
        if (keyframeField === null) {
            return null;
        }
        const nodePath = selection.nodePathInfo.sequenceSubscriptionKey;
        const { keyframeDisplayOffset } = track;
        const sourceFrame = selection.frame - keyframeDisplayOffset;
        if (keyframeField.type === 'sequence') {
            const sequenceFields = (0, timeline_layout_1.getFieldsToShow)({
                schema: track.sequence.controls.schema,
                currentRuntimeValueDotNotation: track.sequence.controls.currentRuntimeValueDotNotation,
                getDragOverrides,
                propStatuses,
                nodePath,
                includeTextContent: false,
            });
            const sequenceField = (_b = sequenceFields === null || sequenceFields === void 0 ? void 0 : sequenceFields.find((candidate) => candidate.key === keyframeField.fieldKey)) !== null && _b !== void 0 ? _b : null;
            const sequencePropStatus = (_c = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[keyframeField.fieldKey]) !== null && _c !== void 0 ? _c : null;
            if (!sequenceField || (sequencePropStatus === null || sequencePropStatus === void 0 ? void 0 : sequencePropStatus.status) !== 'keyframed') {
                return null;
            }
            return {
                type: 'sequence',
                field: sequenceField,
                fieldLabel: (_d = sequenceField.description) !== null && _d !== void 0 ? _d : sequenceField.key,
                fileName: nodePath.absolutePath,
                keyframeDisplayOffset,
                nodePath,
                propStatus: sequencePropStatus,
                schema: track.sequence.controls.schema,
                sourceFrame,
            };
        }
        const effect = track.sequence.effects[keyframeField.effectIndex];
        if (!effect) {
            return null;
        }
        const effectFields = (0, timeline_layout_1.getEffectFieldsToShow)({
            effect,
            effectIndex: keyframeField.effectIndex,
            nodePath,
            propStatuses,
            getEffectDragOverrides,
        });
        const effectField = (_e = effectFields.find((candidate) => candidate.key === keyframeField.fieldKey)) !== null && _e !== void 0 ? _e : null;
        const effectStatus = remotion_1.Internals.getEffectPropStatusesCtx({
            propStatuses,
            nodePath,
            effectIndex: keyframeField.effectIndex,
        });
        const effectPropStatus = effectStatus.type === 'can-update-effect'
            ? ((_f = effectStatus.props[keyframeField.fieldKey]) !== null && _f !== void 0 ? _f : null)
            : null;
        if (!effectField || (effectPropStatus === null || effectPropStatus === void 0 ? void 0 : effectPropStatus.status) !== 'keyframed') {
            return null;
        }
        return {
            type: 'effect',
            effectIndex: keyframeField.effectIndex,
            field: effectField,
            fieldLabel: (_g = effectField.description) !== null && _g !== void 0 ? _g : effectField.key,
            fileName: nodePath.absolutePath,
            keyframeDisplayOffset,
            nodePath,
            propStatus: effectPropStatus,
            schema: effect.schema,
            sourceFrame,
            validatedLocation: {
                source: nodePath.absolutePath,
                line: 1,
                column: 0,
            },
        };
    }, [
        getDragOverrides,
        getEffectDragOverrides,
        propStatuses,
        selection,
        track,
    ]);
    const clearFrameDragOverride = (0, react_1.useCallback)((detailsToClear) => {
        if (detailsToClear === null) {
            return;
        }
        if (detailsToClear.type === 'sequence') {
            clearDragOverrides(detailsToClear.nodePath);
            return;
        }
        clearEffectDragOverrides(detailsToClear.nodePath, detailsToClear.effectIndex);
    }, [clearDragOverrides, clearEffectDragOverrides]);
    const onFrameChange = (0, react_1.useCallback)((value) => {
        const displayFrame = (0, keyframe_inspector_frame_1.clampInspectorKeyframeDisplayFrame)({
            durationInFrames: videoConfig.durationInFrames,
            frame: value,
        });
        setDraftFrame(displayFrame);
        if (details === null) {
            return;
        }
        const toFrame = (0, keyframe_inspector_frame_1.getInspectorKeyframeSourceFrame)({
            displayFrame,
            keyframeDisplayOffset: details.keyframeDisplayOffset,
        });
        if (displayFrame === selection.frame || toFrame === details.sourceFrame) {
            clearFrameDragOverride(details);
            return;
        }
        const dragOverrideValue = makeMovedKeyframedDragOverride({
            details,
            toFrame,
        });
        if (dragOverrideValue === null) {
            clearFrameDragOverride(details);
            return;
        }
        if (details.type === 'sequence') {
            setDragOverrides(details.nodePath, details.field.key, dragOverrideValue);
            return;
        }
        setEffectDragOverrides(details.nodePath, details.effectIndex, details.field.key, dragOverrideValue);
    }, [
        clearFrameDragOverride,
        details,
        selection.frame,
        setDragOverrides,
        setEffectDragOverrides,
        videoConfig.durationInFrames,
    ]);
    const onFrameChangeEnd = (0, react_1.useCallback)((value) => {
        if (details === null || previewServerState.type !== 'connected') {
            clearFrameDragOverride(details);
            setDraftFrame(selection.frame);
            return;
        }
        const displayFrame = (0, keyframe_inspector_frame_1.clampInspectorKeyframeDisplayFrame)({
            durationInFrames: videoConfig.durationInFrames,
            frame: value,
        });
        const toFrame = (0, keyframe_inspector_frame_1.getInspectorKeyframeSourceFrame)({
            displayFrame,
            keyframeDisplayOffset: details.keyframeDisplayOffset,
        });
        setDraftFrame(displayFrame);
        clearFrameDragOverride(details);
        if (displayFrame === selection.frame || toFrame === details.sourceFrame) {
            return;
        }
        if (makeMovedKeyframedDragOverride({ details, toFrame }) === null) {
            setDraftFrame(selection.frame);
            return;
        }
        selectItems([
            {
                ...selection,
                frame: displayFrame,
            },
        ], { reveal: true });
        const move = {
            fileName: details.fileName,
            nodePath: details.nodePath,
            fieldKey: details.field.key,
            fromFrame: details.sourceFrame,
            toFrame,
            schema: details.schema,
        };
        (0, call_move_keyframe_1.callMoveKeyframes)({
            sequenceKeyframes: details.type === 'sequence' ? [move] : [],
            effectKeyframes: details.type === 'effect'
                ? [
                    {
                        ...move,
                        effectIndex: details.effectIndex,
                    },
                ]
                : [],
            setPropStatuses,
            clientId: previewServerState.clientId,
        }).catch(() => undefined);
    }, [
        clearFrameDragOverride,
        details,
        previewServerState,
        selection,
        selectItems,
        setPropStatuses,
        videoConfig.durationInFrames,
    ]);
    const onSelectParent = (0, react_1.useCallback)((event) => {
        event.stopPropagation();
        if (parentSelection === null) {
            return;
        }
        selectItems([parentSelection], { reveal: true });
    }, [parentSelection, selectItems]);
    const removeDisabled = previewServerState.type !== 'connected';
    const onRemoveKeyframe = (0, react_1.useCallback)((event) => {
        event.stopPropagation();
        if (details === null || previewServerState.type !== 'connected') {
            return;
        }
        const easingSelection = (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(details.propStatus.interpolationFunction)
            ? (0, get_easing_selection_after_keyframe_delete_1.getEasingSelectionAfterKeyframeDelete)({
                deletedSourceFrames: [details.sourceFrame],
                keyframeDisplayOffset: details.keyframeDisplayOffset,
                nodePathInfo: selection.nodePathInfo,
                propStatus: details.propStatus,
                timelinePosition,
            })
            : null;
        if (easingSelection !== null) {
            selectItems([easingSelection], { reveal: true });
        }
        else if (parentSelection !== null) {
            selectItems([parentSelection], { reveal: true });
        }
        if (details.type === 'sequence') {
            (0, call_delete_keyframe_1.callDeleteSequenceKeyframe)({
                fileName: details.fileName,
                nodePath: details.nodePath,
                fieldKey: details.field.key,
                sourceFrame: details.sourceFrame,
                schema: details.schema,
                setPropStatuses,
                clientId: previewServerState.clientId,
            }).catch(() => undefined);
            return;
        }
        (0, call_delete_keyframe_1.callDeleteEffectKeyframe)({
            fileName: details.fileName,
            nodePath: details.nodePath,
            effectIndex: details.effectIndex,
            fieldKey: details.field.key,
            sourceFrame: details.sourceFrame,
            schema: details.schema,
            setPropStatuses,
            clientId: previewServerState.clientId,
        }).catch(() => undefined);
    }, [
        details,
        parentSelection,
        previewServerState,
        selectItems,
        selection.nodePathInfo,
        setPropStatuses,
        timelinePosition,
    ]);
    if (details === null || track === null) {
        return jsx_runtime_1.jsx(common_1.InspectorMessage, { children: "Keyframe unavailable" });
    }
    return (jsx_runtime_1.jsxs("div", { style: styles_1.selectedContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: [
            jsx_runtime_1.jsx(SequenceInspectorHeader_1.SequenceInspectorSections, { track: track }), jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(common_1.InspectorBackHeader, { disabled: parentSelection === null, onClick: onSelectParent, title: "Back to property", children: jsx_runtime_1.jsx("div", { style: styles_1.sectionHeaderTitle, children: details.fieldLabel }) }), jsx_runtime_1.jsx(common_1.InspectorSectionDivider, {}), jsx_runtime_1.jsx(KeyframeEasingNavigator_1.KeyframeEasingNavigator, { currentSelection: selection, includeEasings: (0, update_selected_easing_1.canEditEasingForInterpolationFunction)(details.propStatus.interpolationFunction), keyframes: details.propStatus.keyframes.map((keyframe) => ({
                    ...keyframe,
                    frame: keyframe.frame + details.keyframeDisplayOffset,
                })), nodePathInfo: selection.nodePathInfo }), jsx_runtime_1.jsxs("div", { style: styles_1.detailsWithInlineAction, children: [
                    jsx_runtime_1.jsxs("div", { style: styles_1.detailsBeforeInlineAction, children: [
                            jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Frame", children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: draftFrame, status: "ok", onValueChange: onFrameChange, onValueChangeEnd: onFrameChangeEnd, onTextChange: () => undefined, min: 0, max: Math.max(0, videoConfig.durationInFrames - 1), step: 1, formatter: (value) => String(Math.round(Number(value))), rightAlign: true, small: true }) }), jsx_runtime_1.jsxs("div", { style: styles_1.keyframeEditorRow, children: [
                                    jsx_runtime_1.jsx("div", { style: styles_1.keyframeEditorLabel, children: details.fieldLabel }), jsx_runtime_1.jsx("div", { style: styles_1.keyframeEditorValue, children: details.type === 'sequence' ? (jsx_runtime_1.jsx(TimelineSequencePropItem_1.TimelineSequenceKeyframedValue, { field: details.field, fileName: details.fileName, nodePath: details.nodePath, schema: details.schema, propStatus: details.propStatus, sourceFrame: details.sourceFrame })) : (jsx_runtime_1.jsx(TimelineEffectPropItem_1.TimelineEffectPropValue, { field: details.field, nodePath: details.nodePath, validatedLocation: details.validatedLocation, sourceFrame: details.sourceFrame })) })
                                ] })
                        ] }), jsx_runtime_1.jsx(common_1.InspectorInlineAction, { disabled: removeDisabled, onClick: onRemoveKeyframe, renderIcon: (color) => jsx_runtime_1.jsx(TrashIcon, { color: color }), children: "Remove keyframe" })] })
        ] }));
};
exports.KeyframeInspector = KeyframeInspector;
