<template>
    <div
        ref="elRef"
        v-size="{ max: [500, 450] }"
        class="qglefbjs notification"
        :class="firstNotification.type"
    >
        <div class="tail">
            <header>
                <div class="name-wrapper">
                    <template v-for="notif in notificationGroup.value">
                        <MkA
                            v-if="notif.type === 'Renote'"
                            v-user-preview="notif.note.user.id"
                            class="name"
                            :to="userPage(notif.note.user)"
                            ><MkUserName :user="notif.note.user"
                        /></MkA>
                        <MkA
                            v-else-if="notif.type === 'Reaction'"
                            v-user-preview="notif.user.id"
                            class="name"
                            :to="userPage(notif.user)"
                            ><MkUserName :user="notif.user"
                        /></MkA>
                    </template>
                </div>
                <MkTime
                    v-if="withTime"
                    :time="firstNotification.created_at"
                    class="time"
                />
            </header>
            <MkA
                v-if="firstNotification.type === 'Reaction'"
                class="text"
                :to="notePage(firstNotification.note)"
                :title="getNoteSummary(firstNotification.note)"
            >
                <span>{{ i18n.ts._notification.reacted }}</span>
                <i class="ph-quotes ph-fill ph-lg"></i>
                <Mfm
                    :text="getNoteSummary(firstNotification.note)"
                    :plain="true"
                    :nowrap="!full"
                    :custom-emojis="firstNotification.note.emojis"
                />
                <i class="ph-quotes ph-fill ph-lg"></i>
            </MkA>
            <MkA
                v-if="firstNotification.type === 'Renote'"
                class="text"
                :to="notePage(firstNotification.note.renoted_note!)"
                :title="getNoteSummary(firstNotification.note.renoted_note!)"
            >
                <span>{{ i18n.ts._notification.renoted }}</span>
                <i class="ph-quotes ph-fill ph-lg"></i>
                <Mfm
                    :text="getNoteSummary(firstNotification.note.renoted_note!)"
                    :plain="true"
                    :nowrap="!full"
                    :custom-emojis="firstNotification.note.renoted_note!.emojis"
                />
                <i class="ph-quotes ph-fill ph-lg"></i>
            </MkA>
        </div>
        <div class="head-wrapper">
            <div class="head" v-for="notif in notificationGroup.value">
                <MagAvatar
                    v-if="notif.type === 'Renote'"
                    class="icon"
                    :user="notif.note.user"
                />
                <MagAvatar
                    v-else-if="notif.type === 'Reaction'"
                    class="icon"
                    :user="notif.user"
                />
                <div class="sub-icon" :class="notif.type">
                    <i
                        v-if="notif.type === 'Renote'"
                        class="ph-repeat ph-bold"
                    ></i>
                    <!-- notification.reaction が null になることはまずないが、ここでoptional chaining使うと一部ブラウザで刺さるので念の為 -->
                    <MagEmoji
                        v-else-if="
                            showEmojiReactions && notif.type === 'Reaction'
                        "
                        :ref="(el) => hookTooltip(el, notif)"
                        :emoji="notif.reaction"
                        :is-reaction="true"
                        :normal="true"
                        :no-style="true"
                    />
                    <MagEmoji
                        v-else-if="
                            !showEmojiReactions && notif.type === 'Reaction'
                        "
                        :emoji="defaultReaction"
                        :is-reaction="true"
                        :normal="true"
                        :no-style="true"
                    />
                </div>
            </div>
        </div>
    </div>
</template>

<script lang="ts" setup>
import {
    ComponentPublicInstance,
    onMounted,
    onUnmounted,
    Ref,
    ref,
    watch,
} from "vue";
import XReactionTooltip from "@/components/MkReactionTooltip.vue";
import { getNoteSummary } from "@/scripts/get-note-summary";
import { notePage } from "@/filters/note";
import * as os from "@/os";
import { stream } from "@/stream";
import { useTooltip } from "@/scripts/use-tooltip";
import { defaultStore } from "@/store";
import { instance } from "@/instance";
import { packed } from "magnetar-common";
import { i18n } from "@/i18n";
import { userPage } from "@/filters/user";

const props = withDefaults(
    defineProps<{
        notificationGroup: {
            type: "group";
            value: packed.PackNotification[];
            users: packed.PackUserBase[];
            id: string;
            created_at: string;
        };
        withTime?: boolean;
        full?: boolean;
    }>(),
    {
        withTime: false,
        full: false,
    },
);

const firstNotification = ref(props.notificationGroup.value[0]);
watch(
    () => props.notificationGroup.value[0],
    (n) => {
        firstNotification.value = n;
    },
    { deep: true },
);

const emit = defineEmits(["refresh"]);
const elRef = ref<HTMLElement>();
const reactionRefs = ref<Ref<HTMLElement | ComponentPublicInstance>[]>([]);

const showEmojiReactions =
    defaultStore.state.enableEmojiReactions ||
    defaultStore.state.showEmojisInReactionNotifications;
const defaultReaction = ["⭐", "👍", "❤️"].includes(instance.defaultReaction)
    ? instance.defaultReaction
    : "⭐";

let readObserver: IntersectionObserver | undefined;
let connection;

onMounted(() => {
    if (!firstNotification.value.is_read && elRef.value) {
        readObserver = new IntersectionObserver((entries, observer) => {
            if (!entries.some((entry) => entry.isIntersecting)) return;
            stream.send(
                "readNotifications",
                props.notificationGroup.value.map((n) => n.id),
            );
            observer.disconnect();
        });

        readObserver.observe(elRef.value);

        connection = stream.useChannel("main");
        connection.on("readAllNotifications", () => readObserver!.disconnect());

        watch(
            () => firstNotification.value.is_read,
            () => {
                readObserver!.disconnect();
            },
        );
    }
});

onUnmounted(() => {
    if (readObserver) readObserver.disconnect();
    if (connection) connection.dispose();
});

const hookTooltip = (
    el: HTMLElement | ComponentPublicInstance | null,
    notif: packed.PackNotification,
) => {
    if (el == null) return;

    const elRef = ref(el);

    useTooltip(elRef, (showing) => {
        if (notif.type !== "Reaction") return;

        os.popup(
            XReactionTooltip,
            {
                showing,
                reaction: notif.reaction,
                targetElement:
                    "$el" in elRef.value ? elRef.value.$el : elRef.value,
            },
            {},
            "closed",
        );
    });

    reactionRefs.value.push(elRef);
};
</script>

<style lang="scss" scoped>
.qglefbjs {
    position: relative;
    box-sizing: border-box;
    padding: 24px 32px;
    font-size: 0.9em;
    overflow-wrap: break-word;
    display: flex;
    contain: content;
    flex-direction: column;

    &.max-width_500px {
        padding-block: 16px;
        font-size: 0.9em;
    }
    &.max-width_450px {
        padding: 12px 16px;
    }

    > .head-wrapper {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 8px;

        > .head {
            position: relative;
            top: 0;
            flex-shrink: 0;
            width: 42px;
            height: 42px;

            > .icon {
                display: block;
                width: 100%;
                height: 100%;
                border-radius: 6px;
            }

            > .sub-icon {
                position: absolute;
                z-index: 1;
                bottom: -2px;
                right: -2px;
                width: 20px;
                height: 20px;
                box-sizing: border-box;
                border-radius: 100%;
                background: var(--panel);
                box-shadow: 0 0 0 3px var(--panel);
                font-size: 12px;
                text-align: center;

                &:empty {
                    display: none;
                }

                > * {
                    color: #fff;
                    width: 100%;
                    height: 100%;
                }

                &.Renote {
                    padding: 3px;
                    background: #31748f;
                    pointer-events: none;
                }
            }
        }
    }

    > .tail {
        flex: 1;
        min-width: 0;
        margin-block-end: 12px;

        > header {
            display: flex;
            align-items: baseline;
            white-space: nowrap;

            > .name-wrapper {
                display: flex;
                flex-wrap: wrap;
                align-items: baseline;
                margin-inline-end: 10px;
                gap: 0.2em;

                > .name {
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    overflow: hidden;
                    min-width: 0;
                    flex: 0 1 auto;
                }

                > .name:not(:last-child)::after {
                    content: ",";
                }
            }

            > .time {
                margin-left: auto;
                font-size: 0.9em;
            }
        }

        > .text {
            white-space: nowrap;
            display: -webkit-box;
            -webkit-line-clamp: 3;
            -webkit-box-orient: vertical;
            overflow: hidden;
            text-overflow: ellipsis;

            > span:first-child {
                opacity: 0.7;
                &::after {
                    content: ": ";
                }
            }

            > i {
                vertical-align: super;
                font-size: 50%;
                opacity: 0.5;
            }

            > i:first-child {
                margin-right: 4px;
            }

            > i:last-child {
                margin-left: 4px;
            }
        }
    }
}
</style>
