import { __rest } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState } from 'react';
import { styled } from '@mui/material/styles';
import CommentNotification from '../Notification/Comment';
import UserFollowNotification from '../Notification/UserFollow';
import UndeletedForNotification from '../Notification/UndeletedFor';
import DeletedForNotification from '../Notification/DeletedFor';
import UserConnectionNotification from '../Notification/UserConnection';
import PrivateMessageNotification from '../Notification/PrivateMessage';
import UserBlockedNotification from '../Notification/UserBlocked';
import MentionNotification from '../Notification/Mention';
import CollapsedForNotification from '../Notification/CollapsedFor';
import KindlyNoticeForNotification from '../Notification/KindlyNoticeFor';
import KindlyNoticeFlagNotification from '../Notification/KindlyNoticeFlag';
import VoteUpNotification from '../Notification/VoteUp';
import { SCOPE_SC_UI } from '../../constants/Errors';
import PubSub from 'pubsub-js';
import ContributionFollowNotification from '../Notification/ContributionFollow';
import { Avatar, Box, MenuItem, MenuList, Typography } from '@mui/material';
import IncubatorApprovedNotification from '../Notification/IncubatorApproved';
import classNames from 'classnames';
import Skeleton from './Skeleton';
import { SCNotificationObjectTemplateType } from '../../types';
import ScrollContainer from '../../shared/ScrollContainer';
import { FormattedMessage, useIntl } from 'react-intl';
import { SCNotificationTopicType, SCNotificationTypologyType } from '@selfcommunity/types';
import { Endpoints, http } from '@selfcommunity/api-services';
import { Logger } from '@selfcommunity/utils';
import { Link, SCNotification, SCPreferences, SCRoutes, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
import { useThemeProps } from '@mui/system';
import ContributionNotification from '../Notification/Contribution';
import NotificationItem from '../../shared/NotificationItem';
import { PREFIX } from './constants';
import GroupNotification from '../Notification/Group';
import EventNotification from '../Notification/Event/Event';
import LiveStreamNotification from '../Notification/LiveStream';
const classes = {
    root: `${PREFIX}-root`,
    notificationsWrap: `${PREFIX}-notifications-wrap`,
    emptyBoxNotifications: `${PREFIX}-empty-box-notifications`,
    list: `${PREFIX}-list`,
    broadcastMessagesBanner: `${PREFIX}-broadcast-messages-banner`,
    item: `${PREFIX}-item`
};
const Root = styled(Box, {
    name: PREFIX,
    slot: 'Root'
})(() => ({}));
const PREFERENCES = [SCPreferences.LOGO_NAVBAR_LOGO_MOBILE, SCPreferences.TEXT_APPLICATION_NAME];
/**
 * > API documentation for the Community-JS SnippetNotifications component. Learn about the available props and the CSS API.
 *
 *
 * This component renders the notification list.
 * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/SnippetNotifications)

 #### Import

 ```jsx
 import {SnippetNotifications} from '@selfcommunity/react-ui';
 ```

 #### Component Name

 The name `SCSnippetNotifications` can be used when providing style overrides in the theme.


 #### CSS

 |Rule Name|Global class|Description|
 |---|---|---|
 |root|.SCSnippetNotification-root|Styles applied to the root element.|
 |notificationsWrap|.SCSnippetNotification-notification-wrap|Styles applied to the notifications wrap.|
 |emptyBoxNotifications|.SCSnippetNotification-empty-box-notifications|Styles applied to the box indicating that there are no notifications.|
 |list|.SCSnippetNotification-list|Styles applied to the list of notifications.|
 |item|.SCSnippetNotification-item|Styles applied to the single notification.|
 |broadcastMessagesBanner|.SCSnippetNotification-broadcast-messages-banner|Styles applied to the broadcast message banner.|

 * @param inProps
 */
export default function SnippetNotifications(inProps) {
    // PROPS
    const props = useThemeProps({
        props: inProps,
        name: PREFIX
    });
    const { id = `snippetNotifications`, className, showMax = 20, handleCustomNotification, handleNotification, ScrollContainerProps = {}, onNotificationClick, onFetchNotifications } = props, rest = __rest(props, ["id", "className", "showMax", "handleCustomNotification", "handleNotification", "ScrollContainerProps", "onNotificationClick", "onFetchNotifications"]);
    // CONTEXT
    const scUserContext = useSCUser();
    const scRoutingContext = useSCRouting();
    // STATE
    const [notifications, setNotifications] = useState([]);
    const [initialized, setInitialized] = useState(false);
    const [loading, setLoading] = useState(false);
    // REFS
    const notificationSubscription = useRef(null);
    // Compute preferences
    const scPreferences = useSCPreferences();
    const preferences = useMemo(() => {
        const _preferences = {};
        PREFERENCES.map((p) => (_preferences[p] = p in scPreferences.preferences ? scPreferences.preferences[p].value : null));
        return _preferences;
    }, [scPreferences.preferences]);
    // HOOKS
    const intl = useIntl();
    /**
     * Perform vote
     */
    const performFetchNotifications = useMemo(() => () => {
        return http
            .request({
            url: Endpoints.UserNotificationList.url(),
            method: Endpoints.UserNotificationList.method
        })
            .then((res) => {
            if (res.status >= 300) {
                return Promise.reject(res);
            }
            return Promise.resolve(res.data);
        });
    }, []);
    /**
     * Handles vote
     * @param comment
     */
    const fetchNotifications = useMemo(() => () => {
        setInitialized(true);
        if (!loading) {
            setLoading(true);
            performFetchNotifications()
                .then((data) => {
                setNotifications(data.results);
                setLoading(false);
                scUserContext.refreshCounters();
                onFetchNotifications && onFetchNotifications(data.results);
            })
                .catch((error) => {
                Logger.error(SCOPE_SC_UI, error);
            });
        }
    }, [loading, notifications.length, onFetchNotifications, setInitialized]);
    /**
     * Fetch notifications
     */
    useEffect(() => {
        let _t;
        if (scUserContext.user && !initialized) {
            _t = setTimeout(fetchNotifications);
            return () => {
                _t && clearTimeout(_t);
            };
        }
    }, [scUserContext.user, initialized]);
    /**
     * Notification subscriber
     * @param msg
     * @param data
     */
    const notificationSubscriber = (msg, data) => {
        /**
         * Ignore notifications of type: notification_banner
         * (data.data.activity_type === SCNotificationTypologyType.NOTIFICATION_BANNER)
         */
        if (data &&
            data.type === SCNotificationTopicType.INTERACTION &&
            SCNotification.SCNotificationMapping[data.data.activity_type] &&
            !SCNotification.SCSilentSnippetNotifications.includes(data.data.activity_type)) {
            if (data.data.notification_obj) {
                setNotifications([...[{ is_new: true, sid: '', aggregated: [data.data.notification_obj] }], ...notifications]);
            }
        }
    };
    const handleSingleNotificationClick = (e, n) => {
        if (onNotificationClick) {
            onNotificationClick(e, n);
        }
    };
    /**
     * On mount, fetches first page of notifications
     * On mount, subscribe to receive notification updates
     */
    useEffect(() => {
        if (!loading) {
            notificationSubscription.current = PubSub.subscribe(SCNotificationTopicType.INTERACTION, notificationSubscriber);
        }
        return () => {
            notificationSubscription.current && PubSub.unsubscribe(notificationSubscription.current);
        };
    }, [loading]);
    /**
     * Render every single notification in aggregated group
     * @param n
     * @param i
     */
    const renderAggregatedItem = (n, i) => {
        const type = n.type;
        let content;
        if (type === SCNotificationTypologyType.COMMENT || type === SCNotificationTypologyType.NESTED_COMMENT) {
            content = _jsx(CommentNotification, { notificationObject: n, index: i, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.FOLLOW) {
            content = _jsx(ContributionFollowNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.USER_FOLLOW) {
            content = _jsx(UserFollowNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.CONNECTION_REQUEST || type === SCNotificationTypologyType.CONNECTION_ACCEPT) {
            content = _jsx(UserConnectionNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.VOTE_UP) {
            content = _jsx(VoteUpNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.KINDLY_NOTICE_ADVERTISING ||
            type === SCNotificationTypologyType.KINDLY_NOTICE_AGGRESSIVE ||
            type === SCNotificationTypologyType.KINDLY_NOTICE_POOR ||
            type === SCNotificationTypologyType.KINDLY_NOTICE_VULGAR ||
            type === SCNotificationTypologyType.KINDLY_NOTICE_OFFTOPIC) {
            content = _jsx(KindlyNoticeForNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.KINDLY_NOTICE_FLAG) {
            content = _jsx(KindlyNoticeFlagNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.DELETED_FOR_ADVERTISING ||
            type === SCNotificationTypologyType.DELETED_FOR_AGGRESSIVE ||
            type === SCNotificationTypologyType.DELETED_FOR_POOR ||
            type === SCNotificationTypologyType.DELETED_FOR_VULGAR ||
            type === SCNotificationTypologyType.DELETED_FOR_OFFTOPIC) {
            content = _jsx(DeletedForNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.UNDELETED_FOR) {
            content = _jsx(UndeletedForNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.COLLAPSED_FOR_ADVERTISING ||
            type === SCNotificationTypologyType.COLLAPSED_FOR_AGGRESSIVE ||
            type === SCNotificationTypologyType.COLLAPSED_FOR_POOR ||
            type === SCNotificationTypologyType.COLLAPSED_FOR_VULGAR ||
            type === SCNotificationTypologyType.COLLAPSED_FOR_OFFTOPIC) {
            content = _jsx(CollapsedForNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.PRIVATE_MESSAGE) {
            content = _jsx(PrivateMessageNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.BLOCKED_USER || type === SCNotificationTypologyType.UNBLOCKED_USER) {
            content = _jsx(UserBlockedNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.MENTION) {
            content = _jsx(MentionNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.INCUBATOR_APPROVED) {
            content = _jsx(IncubatorApprovedNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.CUSTOM_NOTIFICATION && handleCustomNotification) {
            content = handleCustomNotification(n);
        }
        else if (type === SCNotificationTypologyType.CONTRIBUTION) {
            content = _jsx(ContributionNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (n.type === SCNotificationTypologyType.USER_ADDED_TO_GROUP ||
            n.type === SCNotificationTypologyType.USER_INVITED_TO_JOIN_GROUP ||
            n.type === SCNotificationTypologyType.USER_ACCEPTED_TO_JOIN_GROUP ||
            n.type === SCNotificationTypologyType.USER_REQUESTED_TO_JOIN_GROUP) {
            return _jsx(GroupNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (n.type === SCNotificationTypologyType.USER_ADDED_TO_EVENT ||
            n.type === SCNotificationTypologyType.USER_INVITED_TO_JOIN_EVENT ||
            n.type === SCNotificationTypologyType.USER_ACCEPTED_TO_JOIN_EVENT ||
            n.type === SCNotificationTypologyType.USER_REQUESTED_TO_JOIN_EVENT) {
            return _jsx(EventNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        else if (type === SCNotificationTypologyType.LIVE_STREAM_STARTED) {
            content = _jsx(LiveStreamNotification, { notificationObject: n, template: SCNotificationObjectTemplateType.SNIPPET }, i);
        }
        if (type && handleNotification) {
            /** Override content */
            content = handleNotification(type, n, content);
        }
        return content;
    };
    /**
     * Renders root object
     */
    return (_jsx(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest, { children: _jsx(Box, Object.assign({ className: classes.notificationsWrap }, { children: !initialized || loading ? (_jsx(Skeleton, { elevation: 0 })) : (_jsx(ScrollContainer, Object.assign({}, ScrollContainerProps, { children: _jsxs(MenuList, Object.assign({ className: classes.list, disabledItemsFocusable: true, disableListWrap: true }, { children: [scUserContext.user.unseen_notification_banners_counter ? (_jsx(MenuItem, Object.assign({ className: classNames(classes.item, classes.broadcastMessagesBanner), component: Link, to: scRoutingContext.url(SCRoutes.USER_NOTIFICATIONS_ROUTE_NAME, {}) }, { children: _jsx(NotificationItem, { template: SCNotificationObjectTemplateType.SNIPPET, isNew: true, disableTypography: true, image: _jsx(Avatar, { alt: preferences[SCPreferences.TEXT_APPLICATION_NAME], src: preferences[SCPreferences.LOGO_NAVBAR_LOGO_MOBILE] }), primary: _jsx(Typography, Object.assign({ component: 'div' }, { children: intl.formatMessage({ id: 'ui.snippetNotifications.broadcastMessages', defaultMessage: 'ui.snippetNotifications.broadcastMessages' }, {
                                        count: scUserContext.user.unseen_notification_banners_counter,
                                        b: (...chunks) => _jsx("strong", { children: chunks }),
                                        link: (...chunks) => _jsx(Link, Object.assign({ to: scRoutingContext.url(SCRoutes.USER_NOTIFICATIONS_ROUTE_NAME, {}) }, { children: chunks }))
                                    }) })) }) }), "banner")) : null, notifications.length === 0 ? (_jsx(MenuItem, Object.assign({ className: classes.emptyBoxNotifications }, { children: _jsx(FormattedMessage, { id: "ui.snippetNotifications.noNotifications", defaultMessage: "ui.snippetNotifications.noNotifications" }) }))) : (notifications.slice(0, showMax).map((notificationObject, i) => notificationObject.aggregated.map((n, k) => (_jsx(MenuItem, Object.assign({ className: classes.item, onClick: (e) => handleSingleNotificationClick(e, n), disableRipple: true, disableTouchRipple: true }, { children: renderAggregatedItem(n, i) }), k)))))] })) }))) })) })));
}
