// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { useEffect, useMemo, useState } from 'react';
import { callingComponentLogger } from '../utils/Logger';
/**
 * Helper hook to maintain the video stream lifecycle. This calls onCreateStreamView and onDisposeStreamView
 * appropriately based on react lifecycle events and prop changes.
 *
 * @remarks
 *
 * Notes on handling changes to scaling mode:
 *
 * Ideally we have access to the original StreamRenderView and can call view.updateScalingMode() and do not need to recreate the stream view.
 * However, to support backwards compat we cannot guarantee this. If we don't have access to the original StreamRenderView we need to dispose
 * the old view and create a new one.
 *
 * Supporting both of these scenarios became too complex and fragile. When we introduce a breaking change this should be update to ensure that
 * onCreateStreamView _must_ return a view object with updateScalingMode and update logic in this hook to call view.updateScalingMode instead
 * of recreating the stream.
 *
 * @private
 */
const useVideoStreamLifecycleMaintainer = (props) => {
    const { isMirrored, isScreenSharingOn, isStreamAvailable, onCreateStreamView, onDisposeStreamView, renderElementExists, scalingMode, streamId, isVideoPermitted } = props;
    const [videoStreamViewResult, setVideoStreamViewResult] = useState();
    useEffect(() => {
        var _a;
        if (isVideoPermitted !== false && isStreamAvailable && !renderElementExists) {
            (_a = onCreateStreamView === null || onCreateStreamView === void 0 ? void 0 : onCreateStreamView({
                isMirrored,
                scalingMode
            })) === null || _a === void 0 ? void 0 : _a.then(result => {
                result && setVideoStreamViewResult(result);
            });
        }
        // Always clean up element to make tile up to date and be able to dispose correctly
        return () => {
            if (renderElementExists) {
                // TODO: Remove `if isScreenSharingOn` when we isolate dispose behavior for screen share
                if (!isScreenSharingOn) {
                    onDisposeStreamView === null || onDisposeStreamView === void 0 ? void 0 : onDisposeStreamView();
                }
            }
            else {
                callingComponentLogger.warning('Stream view element does not exist when disposing stream view');
            }
        };
    }, [isMirrored, isScreenSharingOn, isStreamAvailable, onCreateStreamView, onDisposeStreamView, renderElementExists, scalingMode, streamId, isVideoPermitted]);
    // The execution order for above useEffect is onCreateRemoteStreamView =>(async time gap) RenderElement generated => element disposed => onDisposeRemoteStreamView
    // Element disposed could happen during async time gap, which still cause leaks for unused renderElement.
    // Need to do an entire cleanup when remoteTile gets disposed and make sure element gets correctly disposed
    useEffect(() => {
        return () => {
            // TODO: Remove `if isScreenSharingOn` when we isolate dispose behavior for screen share
            if (!isScreenSharingOn) {
                onDisposeStreamView === null || onDisposeStreamView === void 0 ? void 0 : onDisposeStreamView();
            }
        };
    }, [isScreenSharingOn, onDisposeStreamView]);
    return videoStreamViewResult;
};
/**
 * Extension of {@link useVideoStreamLifecycleMaintainer} specifically for local video streams
 *
 * @private
 */
export const useLocalVideoStreamLifecycleMaintainer = (props) => {
    const { onCreateLocalStreamView, onDisposeLocalStreamView } = props;
    const onCreateStreamView = useMemo(() => (options) => {
        return onCreateLocalStreamView === null || onCreateLocalStreamView === void 0 ? void 0 : onCreateLocalStreamView(options);
    }, [onCreateLocalStreamView]);
    const onDisposeStreamView = useMemo(() => () => {
        onDisposeLocalStreamView === null || onDisposeLocalStreamView === void 0 ? void 0 : onDisposeLocalStreamView();
    }, [onDisposeLocalStreamView]);
    return useVideoStreamLifecycleMaintainer(Object.assign(Object.assign({}, props), { onCreateStreamView,
        onDisposeStreamView }));
};
/**
 * Extension of {@link useVideoStreamLifecycleMaintainer} specifically for remote video streams
 *
 * @private
 */
export const useRemoteVideoStreamLifecycleMaintainer = (props) => {
    const { remoteParticipantId, onCreateRemoteStreamView, onDisposeRemoteStreamView } = props;
    const onCreateStreamView = useMemo(() => (options) => {
        return onCreateRemoteStreamView === null || onCreateRemoteStreamView === void 0 ? void 0 : onCreateRemoteStreamView(remoteParticipantId, options);
    }, [onCreateRemoteStreamView, remoteParticipantId]);
    const onDisposeStreamView = useMemo(() => () => {
        onDisposeRemoteStreamView === null || onDisposeRemoteStreamView === void 0 ? void 0 : onDisposeRemoteStreamView(remoteParticipantId);
    }, [onDisposeRemoteStreamView, remoteParticipantId]);
    return useVideoStreamLifecycleMaintainer(Object.assign(Object.assign({}, props), { onCreateStreamView,
        onDisposeStreamView }));
};
//# sourceMappingURL=useVideoStreamLifecycleMaintainer.js.map