import { __rest } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { isEqualTrackRef, isTrackReference, isWeb, log } from '@livekit/components-core';
import { RoomEvent, Track } from 'livekit-client';
import { CarouselLayout, Chat, ConnectionStateToast, GridLayout, LayoutContextProvider, RoomAudioRenderer, useCreateLayoutContext, useParticipants, usePinnedTracks, useTracks } from '@livekit/components-react';
import { ParticipantTile } from './ParticipantTile';
import { ControlBar } from './ControlBar';
import { useEffect } from 'react';
import { useLivestreamCheck } from './useLiveStreamCheck';
import { FocusLayout, FocusLayoutContainer, FocusLayoutContainerNoParticipants } from './FocusLayout';
import { useSCUser } from '@selfcommunity/react-core';
import classNames from 'classnames';
import { styled } from '@mui/material/styles';
import { Box } from '@mui/material';
import { useThemeProps } from '@mui/system';
const PREFIX = 'SCVideoConference';
const classes = {
    root: `${PREFIX}-root`
};
const Root = styled(Box, {
    name: PREFIX,
    slot: 'Root',
    overridesResolver: (props, styles) => styles.root
})(({ theme }) => ({
    '& .lk-chat': {
        height: '100%'
    }
}));
/**
 * The `VideoConference` ready-made component is your drop-in solution for a classic video conferencing application.
 * It provides functionality such as focusing on one participant, grid view with pagination to handle large numbers
 * of participants, basic non-persistent chat, screen sharing, and more.
 *
 */
export function VideoConference(inProps) {
    var _a, _b;
    // PROPS
    const props = useThemeProps({
        props: inProps,
        name: PREFIX
    });
    const { className, chatMessageFormatter, chatMessageDecoder, chatMessageEncoder, SettingsComponent, speakerFocused, disableChat = false, disableMicrophone = false, disableCamera = false, disableShareScreen = false, hideParticipantsList = false, showSettings } = props, rest = __rest(props, ["className", "chatMessageFormatter", "chatMessageDecoder", "chatMessageEncoder", "SettingsComponent", "speakerFocused", "disableChat", "disableMicrophone", "disableCamera", "disableShareScreen", "hideParticipantsList", "showSettings"]);
    // STATE
    const [widgetState, setWidgetState] = React.useState({
        showChat: false,
        unreadMessages: 0,
        showSettings: showSettings || false
    });
    const [focusInitialized, setFocusInitialized] = React.useState(false);
    const lastAutoFocusedScreenShareTrack = React.useRef(null);
    // HOOKS
    const scUserContext = useSCUser();
    const tracks = useTracks([
        { source: Track.Source.Camera, withPlaceholder: true },
        { source: Track.Source.ScreenShare, withPlaceholder: false }
    ], { updateOnlyOn: [RoomEvent.ActiveSpeakersChanged], onlySubscribed: false });
    const participants = useParticipants();
    const layoutContext = useCreateLayoutContext();
    const screenShareTracks = tracks.filter(isTrackReference).filter((track) => track.publication.source === Track.Source.ScreenShare);
    const focusTrack = (_a = usePinnedTracks(layoutContext)) === null || _a === void 0 ? void 0 : _a[0];
    const carouselTracks = tracks.filter((track) => !isEqualTrackRef(track, focusTrack));
    useLivestreamCheck();
    /**
     * widgetUpdate
     * @param state
     */
    const widgetUpdate = (state) => {
        log.debug('updating widget state', state);
        setWidgetState(state);
    };
    /**
     * handleFocusStateChange
     * @param state
     */
    const handleFocusStateChange = (state) => {
        var _a, _b;
        log.debug('updating widget state', state);
        if (state && state.participant) {
            const updatedFocusTrack = tracks.find((tr) => tr.participant.identity === state.participant.identity);
            if (updatedFocusTrack) {
                (_b = (_a = layoutContext.pin).dispatch) === null || _b === void 0 ? void 0 : _b.call(_a, { msg: 'set_pin', trackReference: updatedFocusTrack });
            }
        }
    };
    useEffect(() => {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        // If screen share tracks are published, and no pin is set explicitly, auto set the screen share.
        if (screenShareTracks.some((track) => track.publication.isSubscribed) && lastAutoFocusedScreenShareTrack.current === null) {
            log.debug('Auto set screen share focus:', { newScreenShareTrack: screenShareTracks[0] });
            (_b = (_a = layoutContext.pin).dispatch) === null || _b === void 0 ? void 0 : _b.call(_a, { msg: 'set_pin', trackReference: screenShareTracks[0] });
            lastAutoFocusedScreenShareTrack.current = screenShareTracks[0];
        }
        else if (lastAutoFocusedScreenShareTrack.current &&
            !screenShareTracks.some((track) => { var _a, _b; return track.publication.trackSid === ((_b = (_a = lastAutoFocusedScreenShareTrack.current) === null || _a === void 0 ? void 0 : _a.publication) === null || _b === void 0 ? void 0 : _b.trackSid); })) {
            log.debug('Auto clearing screen share focus.');
            (_d = (_c = layoutContext.pin).dispatch) === null || _d === void 0 ? void 0 : _d.call(_c, { msg: 'clear_pin' });
            lastAutoFocusedScreenShareTrack.current = null;
        }
        if (focusTrack) {
            let updatedFocusTrack;
            const isFocusTrackParticipantExist = participants.find((pt) => pt.identity === focusTrack.participant.identity);
            if (!isFocusTrackParticipantExist) {
                // Focus track is relative to a participant that has left the room
                updatedFocusTrack = tracks.find((tr) => tr.participant.identity === scUserContext.user.id.toString());
                (_f = (_e = layoutContext.pin).dispatch) === null || _f === void 0 ? void 0 : _f.call(_e, { msg: 'set_pin', trackReference: updatedFocusTrack });
            }
            else if (!isTrackReference(focusTrack)) {
                // You are not subscribet to the track
                updatedFocusTrack = tracks.find((tr) => tr.participant.identity === focusTrack.participant.identity && tr.source === focusTrack.source);
                if (updatedFocusTrack !== focusTrack && isTrackReference(updatedFocusTrack)) {
                    (_h = (_g = layoutContext.pin).dispatch) === null || _h === void 0 ? void 0 : _h.call(_g, { msg: 'set_pin', trackReference: updatedFocusTrack });
                }
            }
        }
    }, [
        screenShareTracks.map((ref) => `${ref.publication.trackSid}_${ref.publication.isSubscribed}`).join(),
        (_b = focusTrack === null || focusTrack === void 0 ? void 0 : focusTrack.publication) === null || _b === void 0 ? void 0 : _b.trackSid,
        tracks,
        participants,
        speakerFocused
    ]);
    useEffect(() => {
        var _a, _b;
        if (speakerFocused && !focusInitialized) {
            const speaker = participants.find((pt) => {
                return pt.name === speakerFocused.username;
            });
            if (speaker) {
                const updatedFocusTrack = tracks.find((tr) => {
                    if (tr) {
                        return tr.participant.identity === speaker.identity;
                    }
                    return false;
                });
                (_b = (_a = layoutContext.pin).dispatch) === null || _b === void 0 ? void 0 : _b.call(_a, { msg: 'set_pin', trackReference: updatedFocusTrack });
                setFocusInitialized(true);
            }
        }
    }, [tracks, participants, speakerFocused]);
    return (_jsxs(Root, Object.assign({ className: classNames(className, classes.root, 'lk-video-conference') }, rest, { children: [isWeb() && (_jsxs(LayoutContextProvider, Object.assign({ value: layoutContext, onPinChange: handleFocusStateChange, onWidgetChange: widgetUpdate }, { children: [_jsxs("div", Object.assign({ className: "lk-video-conference-inner" }, { children: [!focusTrack ? (_jsx("div", Object.assign({ className: "lk-grid-layout-wrapper" }, { children: _jsx(GridLayout, Object.assign({ tracks: tracks }, { children: _jsx(ParticipantTile, {}) })) }))) : (_jsx("div", Object.assign({ className: "lk-focus-layout-wrapper" }, { children: hideParticipantsList ? (_jsx(FocusLayoutContainerNoParticipants, { children: focusTrack && _jsx(FocusLayout, { trackRef: focusTrack }) })) : (_jsxs(FocusLayoutContainer, { children: [_jsx(CarouselLayout, Object.assign({ tracks: carouselTracks }, { children: _jsx(ParticipantTile, {}) })), focusTrack && _jsx(FocusLayout, { trackRef: focusTrack })] })) }))), _jsx(ControlBar, { controls: Object.assign({
                                    chat: !disableChat,
                                    microphone: !disableMicrophone,
                                    camera: !disableCamera,
                                    screenShare: !disableShareScreen
                                }, { settings: !!SettingsComponent }) })] })), !disableChat && (_jsx(Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), SettingsComponent && (_jsx("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: _jsx(SettingsComponent, {}) })))] }))), _jsx(RoomAudioRenderer, {}), _jsx(ConnectionStateToast, {})] })));
}
