// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import React, { useCallback, useMemo, useRef } from 'react';
import { useState } from 'react';
import { useAdaptedSelector } from '../hooks/useAdaptedSelector';
import { useHandlers } from '../hooks/useHandlers';
import { LocalDeviceSettings } from '../components/LocalDeviceSettings';
import { StartCallButton } from '../components/StartCallButton';
import { devicePermissionSelector } from '../selectors/devicePermissionSelector';
import { useSelector } from '../hooks/useSelector';
import { CameraButton, DevicesButton, ErrorBar, _useContainerWidth, useTheme } from "../../../../../react-components/src";
import { getCallingSelector } from "../../../../../calling-component-bindings/src";
import { Image, mergeStyles, Panel, PanelType, Stack } from '@fluentui/react';
import { callDetailsContainerStyles, configurationCenteredContent, configurationSectionStyle, deviceConfigurationStackTokens, fillWidth, logoStyles, panelFocusProps, panelStyles, startCallButtonStyleDesktop } from '../styles/CallConfiguration.styles';
import { LocalPreview } from '../components/LocalPreview';
import { callDetailsStyleDesktop, callDetailsStyleMobile, configurationStackTokensDesktop, configurationStackTokensMobile, configurationContainerStyle, selectionContainerStyle, startCallButtonContainerStyleDesktop, startCallButtonContainerStyleMobile, startCallButtonStyleMobile, titleContainerStyleDesktop, titleContainerStyleMobile } from '../styles/CallConfiguration.styles';
import { useLocale } from '../../localization';
import { bannerNotificationStyles } from '../styles/CallPage.styles';
import { usePropsFor } from '../hooks/usePropsFor';
import { ConfigurationPageErrorBar } from '../components/ConfigurationPageErrorBar';
import { _isSafari } from '../utils';
import { VIDEO_EFFECTS_SIDE_PANE_WIDTH_REM, useVideoEffectsPane } from '../components/SidePane/useVideoEffectsPane';
import { SidePane } from '../components/SidePane/SidePane';
import { useIsParticularSidePaneOpen } from '../components/SidePane/SidePaneProvider';
import { localVideoSelector } from '../../CallComposite/selectors/localVideoStreamSelector';
import { SvgWithWordWrapping } from '../components/SvgWithWordWrapping';
import { getMicrophones, getRole } from '../selectors/baseSelectors';
import { getEnvironmentInfo } from '../selectors/baseSelectors';
/**
 * @private
 */
export const ConfigurationPage = (props) => {
    var _a;
    const { startCallHandler, mobileView, modalLayerHostId, joinCallOptions = {
        microphoneCheck: 'requireMicrophoneAvailable'
    } } = props;
    const theme = useTheme();
    const options = useAdaptedSelector(getCallingSelector(DevicesButton));
    const localDeviceSettingsHandlers = useHandlers(LocalDeviceSettings);
    const { video: cameraPermissionGranted, audio: microphonePermissionGranted } = useSelector(devicePermissionSelector);
    const configContainerRef = useRef(null);
    const configWidth = _useContainerWidth(configContainerRef);
    /**
     * We want to stack the two sections (preview and devices) when the container is less than 450 wide.
     * We lose size calculation when the container is less than 450 wide, so we stack the two sections.
     */
    const stackConfig = !!configWidth && configWidth < 450;
    const errorBarProps = usePropsFor(ErrorBar);
    const microphones = useSelector(getMicrophones);
    const environmentInfo = useSelector(getEnvironmentInfo);
    let disableStartCallButton = (!microphonePermissionGranted || (microphones === null || microphones === void 0 ? void 0 : microphones.length) === 0) && joinCallOptions.microphoneCheck === 'requireMicrophoneAvailable';
    const role = useSelector(getRole);
    const isCameraOn = useSelector(localVideoSelector).isAvailable;
    const [cameraLoading, setCameraLoading] = useState(false);
    const switchCamera = useCallback((device, options) => __awaiter(void 0, void 0, void 0, function* () {
        // Only set camera to be loading if we are switching source while the camera is on
        setCameraLoading(isCameraOn);
        try {
            yield localDeviceSettingsHandlers.onSelectCamera(device, options);
        }
        finally {
            setCameraLoading(false);
        }
    }), [localDeviceSettingsHandlers, isCameraOn]);
    const { onToggleCamera } = usePropsFor(CameraButton);
    const toggleCamera = useCallback((options) => __awaiter(void 0, void 0, void 0, function* () {
        // Only set camera to loading if we are turning on the camera (i.e. the camera was off)
        setCameraLoading(!isCameraOn);
        try {
            yield onToggleCamera(options);
        }
        finally {
            setCameraLoading(false);
        }
    }), [isCameraOn, onToggleCamera]);
    let filteredLatestErrors = props.latestErrors;
    // TODO: move this logic to the error bar selector once role is plumbed from the headless SDK
    if (role !== 'Consumer') {
        filteredLatestErrors = filteredLatestErrors.filter(e => e.type !== 'callCameraAccessDenied' && e.type !== 'callCameraAccessDeniedSafari');
    }
    if ((useIsParticularSidePaneOpen('videoeffects') || !isCameraOn) && errorBarProps) {
        filteredLatestErrors = filteredLatestErrors.filter(e => e.type !== 'unableToStartVideoEffect');
    }
    if (role === 'Consumer') {
        // If user's role permissions do not allow access to the microphone button then DO NOT disable the start call button
        // because microphone device permission is not needed for the user's role
        disableStartCallButton = false;
    }
    const locale = useLocale();
    const title = locale.strings.call.configurationPageTitle.length > 0 ? React.createElement(Stack.Item, { className: mobileView ? titleContainerStyleMobile(theme) : titleContainerStyleDesktop(theme) },
        React.createElement(SvgWithWordWrapping, { width: mobileView ? 325 : 445, lineHeightPx: 16 * 1.5, bufferHeightPx: 16, text: locale.strings.call.configurationPageTitle, role: "heading" })) : React.createElement(React.Fragment, null);
    const callDescription = locale.strings.call.configurationPageCallDetails && React.createElement(Stack.Item, { className: mobileView ? callDetailsStyleMobile(theme) : callDetailsStyleDesktop(theme) }, locale.strings.call.configurationPageCallDetails);
    const mobileWithPreview = mobileView && role !== 'Consumer'; // When permission API is not available, we want to show screen saying checking for access (disappears on its own)
    // then based on permission setting, we show permission denied or nothing
    const { toggleVideoEffectsPane, closeVideoEffectsPane, isVideoEffectsPaneOpen } = useVideoEffectsPane(props.updateSidePaneRenderer, mobileView, props.latestErrors, props.onDismissError);
    const startCall = useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        closeVideoEffectsPane();
        startCallHandler();
    }), [startCallHandler, closeVideoEffectsPane]);
    const panelLayerProps = useMemo(() => ({
        hostId: modalLayerHostId
    }), [modalLayerHostId]);
    const filteredErrorBarProps = useMemo(() => (Object.assign(Object.assign({}, errorBarProps), { activeErrorMessages: filteredLatestErrors })), [errorBarProps, filteredLatestErrors]);
    const containerStyles = useMemo(() => { var _a; return configurationContainerStyle(!mobileView, (_a = props.backgroundImage) === null || _a === void 0 ? void 0 : _a.url); }, [mobileView, (_a = props.backgroundImage) === null || _a === void 0 ? void 0 : _a.url]);
    return React.createElement("div", { ref: configContainerRef, className: mergeStyles(containerStyles) },
        React.createElement(Stack, { styles: bannerNotificationStyles },
            React.createElement(ConfigurationPageErrorBar, { errorBarProps: filteredErrorBarProps, onDismissError: props.onDismissError })),
        React.createElement(Stack, { verticalFill: true, grow: true, horizontal: true, className: fillWidth },
            React.createElement(Stack, { className: configurationCenteredContent(mobileWithPreview, !!props.logo), verticalAlign: stackConfig && !mobileView ? undefined : 'center', verticalFill: mobileWithPreview, tokens: mobileWithPreview ? configurationStackTokensMobile : configurationStackTokensDesktop },
                React.createElement(Stack.Item, { styles: callDetailsContainerStyles },
                    React.createElement(Logo, { logo: props.logo }),
                    title,
                    callDescription),
                React.createElement(Stack, { horizontal: configHorizontal(mobileWithPreview, mobileView, stackConfig), horizontalAlign: mobileWithPreview ? 'stretch' : 'center', verticalFill: mobileWithPreview, tokens: deviceConfigurationStackTokens },
                    role !== 'Consumer' && React.createElement(LocalPreview, { mobileView: mobileWithPreview, showDevicesButton: mobileView, onToggleCamera: toggleCamera, cameraLoading: cameraLoading && !isCameraOn }),
                    React.createElement(Stack, { styles: mobileView ? undefined : configurationSectionStyle },
                        !mobileWithPreview && React.createElement(Stack, { className: mobileView ? undefined : selectionContainerStyle(theme, _isSafari(environmentInfo)) },
                            React.createElement(LocalDeviceSettings, Object.assign({}, options, localDeviceSettingsHandlers, { onSelectCamera: switchCamera, cameraPermissionGranted: cameraPermissionGrantedTrampoline(cameraPermissionGranted), microphonePermissionGranted: micPermissionGrantedTrampoline(microphonePermissionGranted), onClickVideoEffects: toggleVideoEffectsPane }))),
                        React.createElement(Stack, { styles: mobileWithPreview ? startCallButtonContainerStyleMobile : startCallButtonContainerStyleDesktop, horizontalAlign: mobileWithPreview ? 'stretch' : 'end' },
                            React.createElement(StartCallButton, { className: mobileWithPreview ? startCallButtonStyleMobile : startCallButtonStyleDesktop, onClick: startCall, disabled: disableStartCallButton, hideIcon: true }))))),
            React.createElement(Panel, { isOpen: isVideoEffectsPaneOpen, hasCloseButton: false, isBlocking: false, isHiddenOnDismiss: false, styles: panelStyles, focusTrapZoneProps: panelFocusProps, layerProps: panelLayerProps, type: PanelType.custom, customWidth: `${VIDEO_EFFECTS_SIDE_PANE_WIDTH_REM}rem` },
                React.createElement(SidePane, { ariaLabel: isVideoEffectsPaneOpen ? locale.strings.call.videoEffectsPaneAriaLabel : undefined, mobileView: props.mobileView, updateSidePaneRenderer: props.updateSidePaneRenderer, maxWidth: `${VIDEO_EFFECTS_SIDE_PANE_WIDTH_REM}rem`, minWidth: `${VIDEO_EFFECTS_SIDE_PANE_WIDTH_REM}rem` }))));
};
const cameraPermissionGrantedTrampoline = (cameraPermissionGranted, videoState) => {
    return cameraPermissionGranted;
};
const micPermissionGrantedTrampoline = (microphonePermissionGranted, audioState) => {
    return microphonePermissionGranted;
};
const Logo = (props) => {
    if (!props.logo) {
        return React.createElement(React.Fragment, null);
    }
    return React.createElement(Image, { styles: logoStyles(props.logo.shape), src: props.logo.url, alt: props.logo.alt });
};
const configHorizontal = (mobileWithPreview, isMobile, configTooNarrow) => {
    if (configTooNarrow && !isMobile) {
        return false;
    }
    return !mobileWithPreview;
};
//# sourceMappingURL=ConfigurationPage.js.map