"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CompositionDimensions = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const colors_1 = require("../../helpers/colors");
const is_composition_still_1 = require("../../helpers/is-composition-still");
const resolved_stack_to_symbolicated_1 = require("../../helpers/resolved-stack-to-symbolicated");
const InputDragger_1 = require("../NewComposition/InputDragger");
const NotificationCenter_1 = require("../Notifications/NotificationCenter");
const actions_1 = require("../RenderQueue/actions");
const use_resolved_stack_1 = require("../Timeline/use-resolved-stack");
const common_1 = require("./common");
const optimistic_composition_metadata_1 = require("./optimistic-composition-metadata");
const styles_1 = require("./styles");
const fieldLabels = {
    durationInFrames: 'Duration',
    fps: 'Frame rate',
    height: 'Height',
    width: 'Width',
};
const computedStyle = {
    color: colors_1.WHITE_ALPHA_40,
    fontFamily: 'sans-serif',
    fontSize: 12,
    fontStyle: 'italic',
    lineHeight: '16px',
    userSelect: 'none',
};
const dimensionsControls = {
    alignItems: 'center',
    display: 'flex',
    fontFamily: 'sans-serif',
    fontSize: 12,
    gap: 4,
    justifyContent: 'flex-end',
    lineHeight: '16px',
    minWidth: 0,
};
const CompositionMetadataValue = ({ compositionId, computed, disabled, field, onPendingValue, onPendingValueAccepted, onPendingValueFailed, pendingValue, resolvedConfig, symbolicatedStack, value, }) => {
    var _a;
    const [dragValue, setDragValue] = (0, react_1.useState)(null);
    const save = (0, react_1.useCallback)((newValue) => {
        var _a;
        if (newValue === ((_a = pendingValue === null || pendingValue === void 0 ? void 0 : pendingValue.value) !== null && _a !== void 0 ? _a : value)) {
            setDragValue(null);
            return;
        }
        if (symbolicatedStack === null) {
            setDragValue(null);
            (0, NotificationCenter_1.showNotification)('Could not determine where this composition is defined', 2000);
            return;
        }
        const codemod = {
            type: 'update-composition-metadata',
            idToUpdate: compositionId,
            newDurationInFrames: field === 'durationInFrames' ? newValue : null,
            newFps: field === 'fps' ? newValue : null,
            newHeight: field === 'height' ? newValue : null,
            newWidth: field === 'width' ? newValue : null,
        };
        const optimisticValue = {
            baseline: resolvedConfig,
            status: 'saving',
            value: newValue,
        };
        onPendingValue(field, optimisticValue);
        setDragValue(null);
        (0, actions_1.applyCodemod)({
            codemod,
            dryRun: false,
            signal: new AbortController().signal,
            symbolicatedStack,
        })
            .then((result) => {
            if (!result.success) {
                onPendingValueFailed(field, optimisticValue);
                (0, NotificationCenter_1.showNotification)(`Could not update composition ${field}: ${result.reason}`, 2000);
                return;
            }
            onPendingValueAccepted(field, optimisticValue);
        })
            .catch((error) => {
            onPendingValueFailed(field, optimisticValue);
            (0, NotificationCenter_1.showNotification)(`Could not update composition ${field}: ${error.message}`, 2000);
        });
    }, [
        compositionId,
        field,
        onPendingValue,
        onPendingValueAccepted,
        onPendingValueFailed,
        pendingValue === null || pendingValue === void 0 ? void 0 : pendingValue.value,
        resolvedConfig,
        symbolicatedStack,
        value,
    ]);
    const isFps = field === 'fps';
    const formatValue = (0, react_1.useCallback)((newValue) => {
        const numberValue = Number(newValue);
        if (field === 'fps') {
            return `${numberValue}fps`;
        }
        const roundedValue = Math.round(numberValue);
        if (field === 'durationInFrames') {
            return `${roundedValue} ${roundedValue === 1 ? 'frame' : 'frames'}`;
        }
        return String(roundedValue);
    }, [field]);
    return computed ? (jsx_runtime_1.jsx("span", { style: computedStyle, children: formatValue(value) })) : disabled ? (formatValue(value)) : (jsx_runtime_1.jsx(InputDragger_1.InputDragger, { "aria-label": fieldLabels[field], type: "number", value: (_a = dragValue !== null && dragValue !== void 0 ? dragValue : pendingValue === null || pendingValue === void 0 ? void 0 : pendingValue.value) !== null && _a !== void 0 ? _a : value, disabled: pendingValue !== null, status: "ok", onValueChange: setDragValue, onValueChangeEnd: save, onTextChange: () => undefined, min: isFps ? 0.01 : 1, step: isFps ? 0.01 : 1, dragDecimalPlaces: isFps ? 2 : 0, formatter: formatValue, rightAlign: true, small: true }));
};
const CompositionDimensions = ({ compositionId, disabled, stack }) => {
    var _a, _b, _c, _d;
    const video = remotion_1.Internals.useVideo();
    const resolvedVideoConfig = remotion_1.Internals.useResolvedVideoConfig(compositionId);
    const resolvedConfig = (resolvedVideoConfig === null || resolvedVideoConfig === void 0 ? void 0 : resolvedVideoConfig.type) === 'success' ||
        (resolvedVideoConfig === null || resolvedVideoConfig === void 0 ? void 0 : resolvedVideoConfig.type) === 'success-and-refreshing'
        ? resolvedVideoConfig.result
        : null;
    const resolvedConfigRef = (0, react_1.useRef)(resolvedConfig);
    resolvedConfigRef.current = resolvedConfig;
    const [pendingValues, setPendingValues] = (0, react_1.useState)({});
    const resolvedLocation = (0, use_resolved_stack_1.useResolvedStack)(stack);
    const symbolicatedStack = (0, react_1.useMemo)(() => (0, resolved_stack_to_symbolicated_1.resolvedStackToSymbolicated)(resolvedLocation), [resolvedLocation]);
    (0, react_1.useEffect)(() => {
        if (resolvedConfig === null) {
            return;
        }
        setPendingValues((pending) => (0, optimistic_composition_metadata_1.reconcilePendingCompositionMetadata)({
            currentConfig: resolvedConfig,
            pending,
        }));
    }, [resolvedConfig]);
    const onPendingValue = (0, react_1.useCallback)((field, value) => {
        setPendingValues((pending) => ({ ...pending, [field]: value }));
    }, []);
    const onPendingValueAccepted = (0, react_1.useCallback)((field, value) => {
        setPendingValues((pending) => {
            if (resolvedConfigRef.current === null) {
                return pending;
            }
            return (0, optimistic_composition_metadata_1.acceptPendingCompositionMetadataValue)({
                currentConfig: resolvedConfigRef.current,
                field,
                pending,
                value,
            });
        });
    }, []);
    const onPendingValueFailed = (0, react_1.useCallback)((field, value) => {
        setPendingValues((pending) => (0, optimistic_composition_metadata_1.failPendingCompositionMetadataValue)({ field, pending, value }));
    }, []);
    if (video === null || resolvedConfig === null) {
        return null;
    }
    const metadataSource = (resolvedVideoConfig === null || resolvedVideoConfig === void 0 ? void 0 : resolvedVideoConfig.type) === 'success' ||
        (resolvedVideoConfig === null || resolvedVideoConfig === void 0 ? void 0 : resolvedVideoConfig.type) === 'success-and-refreshing'
        ? resolvedVideoConfig.metadataSource
        : undefined;
    const widthIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.width) === 'calculate-metadata';
    const heightIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.height) === 'calculate-metadata';
    const fpsIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.fps) === 'calculate-metadata';
    const durationIsComputed = (metadataSource === null || metadataSource === void 0 ? void 0 : metadataSource.durationInFrames) === 'calculate-metadata';
    const isStill = (0, is_composition_still_1.isCompositionStill)(video);
    return (jsx_runtime_1.jsxs("div", { style: styles_1.detailsContainer, children: [
            jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Dimensions", children: jsx_runtime_1.jsxs("div", { style: dimensionsControls, children: [
                        jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: widthIsComputed, disabled: disabled, field: "width", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_a = pendingValues.width) !== null && _a !== void 0 ? _a : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.width }), jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: heightIsComputed, disabled: disabled, field: "height", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_b = pendingValues.height) !== null && _b !== void 0 ? _b : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.height })
                    ] }) }), isStill ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
                    jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Frame rate", children: jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: fpsIsComputed, disabled: disabled, field: "fps", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_c = pendingValues.fps) !== null && _c !== void 0 ? _c : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.fps }) }), jsx_runtime_1.jsx(common_1.InspectorDetailRow, { label: "Duration", children: jsx_runtime_1.jsx(CompositionMetadataValue, { compositionId: compositionId, computed: durationIsComputed, disabled: disabled, field: "durationInFrames", onPendingValue: onPendingValue, onPendingValueAccepted: onPendingValueAccepted, onPendingValueFailed: onPendingValueFailed, pendingValue: (_d = pendingValues.durationInFrames) !== null && _d !== void 0 ? _d : null, resolvedConfig: resolvedConfig, symbolicatedStack: symbolicatedStack, value: video.durationInFrames }) })
                ] }))] }));
};
exports.CompositionDimensions = CompositionDimensions;
