"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VideoConference = void 0;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const React = tslib_1.__importStar(require("react"));
const components_core_1 = require("@livekit/components-core");
const livekit_client_1 = require("livekit-client");
const components_react_1 = require("@livekit/components-react");
const ParticipantTile_1 = require("./ParticipantTile");
const ControlBar_1 = require("./ControlBar");
const react_1 = require("react");
const useLiveStreamCheck_1 = require("./useLiveStreamCheck");
const FocusLayout_1 = require("./FocusLayout");
const react_core_1 = require("@selfcommunity/react-core");
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const styles_1 = require("@mui/material/styles");
const material_1 = require("@mui/material");
const system_1 = require("@mui/system");
const PREFIX = 'SCVideoConference';
const classes = {
    root: `${PREFIX}-root`
};
const Root = (0, styles_1.styled)(material_1.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.
 *
 */
function VideoConference(inProps) {
    var _a, _b;
    // PROPS
    const props = (0, system_1.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 = tslib_1.__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 = (0, react_core_1.useSCUser)();
    const tracks = (0, components_react_1.useTracks)([
        { source: livekit_client_1.Track.Source.Camera, withPlaceholder: true },
        { source: livekit_client_1.Track.Source.ScreenShare, withPlaceholder: false }
    ], { updateOnlyOn: [livekit_client_1.RoomEvent.ActiveSpeakersChanged], onlySubscribed: false });
    const participants = (0, components_react_1.useParticipants)();
    const layoutContext = (0, components_react_1.useCreateLayoutContext)();
    const screenShareTracks = tracks.filter(components_core_1.isTrackReference).filter((track) => track.publication.source === livekit_client_1.Track.Source.ScreenShare);
    const focusTrack = (_a = (0, components_react_1.usePinnedTracks)(layoutContext)) === null || _a === void 0 ? void 0 : _a[0];
    const carouselTracks = tracks.filter((track) => !(0, components_core_1.isEqualTrackRef)(track, focusTrack));
    (0, useLiveStreamCheck_1.useLivestreamCheck)();
    /**
     * widgetUpdate
     * @param state
     */
    const widgetUpdate = (state) => {
        components_core_1.log.debug('updating widget state', state);
        setWidgetState(state);
    };
    /**
     * handleFocusStateChange
     * @param state
     */
    const handleFocusStateChange = (state) => {
        var _a, _b;
        components_core_1.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 });
            }
        }
    };
    (0, react_1.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) {
            components_core_1.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); })) {
            components_core_1.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 (!(0, components_core_1.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 && (0, components_core_1.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
    ]);
    (0, react_1.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 ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root, 'lk-video-conference') }, rest, { children: [(0, components_core_1.isWeb)() && ((0, jsx_runtime_1.jsxs)(components_react_1.LayoutContextProvider, Object.assign({ value: layoutContext, onPinChange: handleFocusStateChange, onWidgetChange: widgetUpdate }, { children: [(0, jsx_runtime_1.jsxs)("div", Object.assign({ className: "lk-video-conference-inner" }, { children: [!focusTrack ? ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-grid-layout-wrapper" }, { children: (0, jsx_runtime_1.jsx)(components_react_1.GridLayout, Object.assign({ tracks: tracks }, { children: (0, jsx_runtime_1.jsx)(ParticipantTile_1.ParticipantTile, {}) })) }))) : ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-focus-layout-wrapper" }, { children: hideParticipantsList ? ((0, jsx_runtime_1.jsx)(FocusLayout_1.FocusLayoutContainerNoParticipants, { children: focusTrack && (0, jsx_runtime_1.jsx)(FocusLayout_1.FocusLayout, { trackRef: focusTrack }) })) : ((0, jsx_runtime_1.jsxs)(FocusLayout_1.FocusLayoutContainer, { children: [(0, jsx_runtime_1.jsx)(components_react_1.CarouselLayout, Object.assign({ tracks: carouselTracks }, { children: (0, jsx_runtime_1.jsx)(ParticipantTile_1.ParticipantTile, {}) })), focusTrack && (0, jsx_runtime_1.jsx)(FocusLayout_1.FocusLayout, { trackRef: focusTrack })] })) }))), (0, jsx_runtime_1.jsx)(ControlBar_1.ControlBar, { controls: Object.assign({
                                    chat: !disableChat,
                                    microphone: !disableMicrophone,
                                    camera: !disableCamera,
                                    screenShare: !disableShareScreen
                                }, { settings: !!SettingsComponent }) })] })), !disableChat && ((0, jsx_runtime_1.jsx)(components_react_1.Chat, { style: { display: widgetState.showChat ? 'grid' : 'none' }, messageFormatter: chatMessageFormatter, messageEncoder: chatMessageEncoder, messageDecoder: chatMessageDecoder })), SettingsComponent && ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: "lk-settings-menu-modal", style: { display: widgetState.showSettings ? 'block' : 'none' } }, { children: (0, jsx_runtime_1.jsx)(SettingsComponent, {}) })))] }))), (0, jsx_runtime_1.jsx)(components_react_1.RoomAudioRenderer, {}), (0, jsx_runtime_1.jsx)(components_react_1.ConnectionStateToast, {})] })));
}
exports.VideoConference = VideoConference;
