<template>
    <div class="bg-neutral-900 w-full h-full relative">
        <video
            v-show="playUrl"
            ref="video"
            playsinline
            :src="playUrl"
            :poster="series?.cover"
            :controls="false"
            class="object-contain w-full h-full"
            @play="onVideoDidPlay"
            @pause="onVideoDidPause"
            @click="exitImmersive"
            @ended="emit('ended')"
        ></video>
        <img
            v-show="!playUrl && series"
            :src="series?.cover"
            class="object-contain w-full h-full"
        />
        <Transition name="fade">
            <div
                v-show="!hideControls"
                class="mask-info absolute w-full h-full top-0 left-0"
                @click="enterImmersive"
            >
                <IonSpinner
                    v-if="!series || !episode"
                    name="crescent"
                    class="absolute left-0 top-0 right-0 bottom-0 m-auto text-lg"
                />
                <template v-if="!loading">
                    <IonIcon
                        v-if="showPlayBtn"
                        :icon="playCircle"
                        class="absolute left-0 top-0 right-0 bottom-0 m-auto text-7xl opacity-60"
                        @click.stop="onPlay"
                    />
                    <IonIcon
                        v-else
                        :icon="pauseCircle"
                        class="absolute left-0 top-0 right-0 bottom-0 m-auto text-7xl opacity-60"
                        @click.stop="playing = false"
                    />
                </template>
                <div class="tool-bar flex">
                    <div class="px-2 flex items-center" @click.stop="router.back()">
                        <IonIcon
                            :icon="chevronBack"
                            class="text-2xl opacity-80 h-10"
                        />
                    </div>
                    <div class="flex-1"></div>
                    <div class="px-4 flex items-center">
                        <IonIcon
                            :icon="ellipsisHorizontal"
                            class="text-2xl opacity-80 h-10"
                        />
                    </div>
                </div>
                <div
                    class="title-info absolute bottom-0 left-0 right-0 drop-shadow px-4"
                    v-show="series"
                >
                    <div class="pr-20">
                        <div class="text-base line-clamp-1">
                            {{ series?.title }}
                        </div>
                        <div class="text-sm text-opacity-80 text-white">
                            Episode {{ episode?.episodeNum }}
                        </div>
                    </div>
                    <div ref="dragTarget" class="py-3">
                        <div
                            class="progress-bar h-[2px] bg-white bg-opacity-20 rounded"
                            ref="progressBar"
                        >
                            <div
                                v-if="loading"
                                class="loading bg-white h-[2px] rounded bg-opacity-80"
                            ></div>
                            <div
                                v-else
                                class="progress bg-white h-[2px] rounded bg-opacity-80"
                                :style="{ width: progress + '%' }"
                            ></div>
                        </div>
                    </div>
                    <div
                        class="dive-into h-[44px] flex items-center text-xs bg-opacity-20 bg-black px-4 rounded"
                        @click.stop="showEpisodesModal = true"
                    >
                        <IonIcon :icon="filter" class="text-base" />
                        <div class="flex-1 ml-2 text-white text-opacity-80">
                            {{ series?.totalEpisodes }} Episodes
                        </div>
                        <IonIcon :icon="chevronForward" class="text-base" />
                    </div>
                </div>

                <div
                    class="absolute right-4 bottom-32 flex flex-col"
                    v-if="series"
                >
                    <div
                        class="btn flex flex-col items-center justify-center"
                        @click.stop="emit('save')"
                    >
                        <IonIcon
                            :class="{ 'text-prim': saved }"
                            :icon="bookmark"
                            class="text-4xl opacity-80"
                        />
                        <div class="text-xs">
                            {{ saved ? "Saved" : "Save" }}
                        </div>
                    </div>
                    <div
                        class="btn flex flex-col items-center justify-center mt-4"
                    >
                        <IonIcon
                            :icon="arrowRedo"
                            class="text-4xl opacity-80"
                        />
                        <div class="text-xs">Share</div>
                    </div>
                </div>
            </div>
        </Transition>
        <div
            class="absolute left-4 right-4 bottom-24 shadow"
            v-if="draggingData.dragging"
        >
            <div
                class="text-center text-xl font-bold mb-2 drop-shadow text-white text-opacity-50"
            >
                <span
                    class="inline-block text-center w-16 text-white text-opacity-90"
                >
                    {{
                        formatDuration(
                            (duration * draggingData.toProgress) / 100
                        )
                    }}
                </span>
                /
                <span class="inline-block text-center w-16">
                    {{ formatDuration(duration) }}
                </span>
            </div>
            <div class="progress-bar-large h-2 bg-white bg-opacity-20 rounded">
                <div
                    class="progress bg-white h-2 rounded bg-opacity-80"
                    :style="{ width: draggingData.toProgress + '%' }"
                ></div>
            </div>
        </div>
        <ion-modal
            ref="modal"
            class="episodes-modal"
            :is-open="showEpisodesModal"
            :initial-breakpoint="1"
            :breakpoints="[0, 1]"
            @ionModalDidDismiss="showEpisodesModal = false"
        >
            <ion-content>
                <div class="flex flex-col h-full">
                    <div class="text-lg mt-4 mx-4">{{ series?.title }}</div>
                    <div class="text-sm mt-1 mx-4 text-white text-opacity-80">
                        {{ series?.totalEpisodes }} Episodes
                    </div>
                    <div
                        class="flex-1 flex flex-wrap overflow-auto mt-4 ml-4 mr-1"
                    >
                        <div
                            class="pr-3 w-1/4 mb-3"
                            v-for="(item, n) in episodes || []"
                            :key="item.id"
                            @click="chooseEpisode(n)"
                        >
                            <div
                                class="episode-btn h-10 bg-neutral-800 rounded flex items-center justify-center relative"
                                :class="{ active: item.id === episode?.id }"
                            >
                                <IonIcon
                                    v-if="parseInt(item.price) > 0"
                                    :icon="lockClosed"
                                    class="absolute top-1 right-1 text-sm"
                                />
                                {{ item.episodeNum }}
                            </div>
                        </div>
                    </div>
                </div>
            </ion-content>
        </ion-modal>
    </div>
</template>
<script setup lang="ts">
import {
    Ref,
    computed,
    nextTick,
    onBeforeUnmount,
    onMounted,
    reactive,
    ref,
    watch,
} from "vue";
import {
    IonIcon,
    IonSpinner,
    useIonRouter,
    IonModal,
    IonContent,
    IonLabel,
    IonButton,
} from "@ionic/vue";
import { useDrag } from "@vueuse/gesture";
import { useElementBounding, useMediaControls } from "@vueuse/core";
import {
    chevronForward,
    chevronBack,
    arrowRedo,
    bookmark,
    ellipsisHorizontal,
    playCircle,
    pauseCircle,
    filter,
    lockClosed,
} from "ionicons/icons";
import http from "@/plugins/http";
import { watchThrottled } from "@vueuse/core";
import emitter from "@/events";

const props = defineProps({
    active: Boolean,
    series: Object,
    episode: Object,
    episodes: Array<any>,
    saved: Boolean,
});
const emit = defineEmits(["chooseEpisode", "save", "ended", "pay"]);
const router = useIonRouter();
const video: Ref<HTMLVideoElement | null> = ref(null);
const { playing, currentTime, duration, volume } = useMediaControls(video);
const showPauseBtn = ref(false);
const progress = computed(() => {
    if (isNaN(duration.value) || duration.value === 0) return 0;
    return (currentTime.value / duration.value) * 100;
});
const loading = ref(false);
const dragTarget = ref();
const progressBar: Ref<HTMLElement | null> = ref(null);
const draggingData = reactive({
    barWidth: 0,
    videoDuration: 0,
    progress: 0,
    toProgress: 0,
    dragging: false,
});
const playUrl = ref("");
const needPay = ref(false);
const showEpisodesModal = ref(false);
const immersive = ref(false);

const showPlayBtn = computed(() => {
    if (!props.series || loading.value) return false;
    if (!playUrl.value) return true;
    if (!playing.value) return true;
    return false;
});

const hideControls = computed(() => {
    return draggingData.dragging || (playing.value && immersive.value);
});

function formatDuration(duration: number) {
    if (isNaN(duration)) return "00:00";
    const minutes = Math.floor(duration / 60)
        .toString()
        .padStart(2, "0");
    const seconds = Math.floor(duration % 60)
        .toString()
        .padStart(2, "0");
    return `${minutes}:${seconds}`;
}

const dragHandler = ({ movement: [x, y], dragging }: any) => {
    if (dragging && !draggingData.dragging) {
        draggingData.barWidth = useElementBounding(progressBar).width.value;
        draggingData.videoDuration = duration.value;
        draggingData.progress = progress.value;
        draggingData.toProgress = progress.value;
        draggingData.dragging = true;
    }
    draggingData.toProgress = Math.max(
        0,
        Math.min(
            100,
            draggingData.progress +
                Math.floor((x / draggingData.barWidth) * 100)
        )
    );
    if (!dragging) {
        draggingData.dragging = false;
        currentTime.value = (duration.value * draggingData.toProgress) / 100;
    }
    console.log(JSON.stringify(draggingData));
};

function getEpisode() {
    if (!props.episode) return;
    loading.value = true;
    try {
        http.get(`/episodes/${props.episode?.id}`).then((res) => {
            if (res.playUrl) {
                playUrl.value = res.playUrl;
            } else {
                needPay.value = true;
            }
            if (props.active) {
                nextTick(() => {
                    onPlay();
                });
            }
        });
    } catch (error) {
        console.error(error);
    }
    loading.value = false;
}
useDrag(dragHandler, {
    domTarget: dragTarget,
    eventOptions: {
        capture: true,
    },
});
function onPaymentSuccess() {
    console.log("onPaymentSuccess");
    setTimeout(() => {
        getEpisode();
    }, 100);
}
onMounted(() => {
    getEpisode();
    emitter.on("payment-success", onPaymentSuccess);
});
onBeforeUnmount(() => {
    emitter.off("payment-success", onPaymentSuccess);
});
watch(
    () => props.episode,
    () => {
        getEpisode();
    }
);
watch(
    () => props.active,
    (active) => {
        if (active) {
            onPlay();
        } else {
            playing.value = false;
        }
    }
);

async function onPlay() {
    if (needPay.value) {
        try {
            http.get(`/episodes/${props.episode?.id}`).then((res) => {
                if (res.playUrl) {
                    playUrl.value = res.playUrl;
                } else {
                    needPay.value = true;
                }
            });
        } catch (error) {
            console.error(error);
        }
    }
    if (playUrl.value) {
        playing.value = true;
    } else if (needPay.value) {
        emit("pay");
    }
}

function chooseEpisode(n: number) {
    showEpisodesModal.value = false;
    setTimeout(() => {
        emit("chooseEpisode", n);
    }, 100);
}

const videoPlayTimeout = ref<any>(0);
const immersiveTimeout = ref<any>(0);

function enterImmersive() {
    if (playing.value) {
        console.log("enterImmersive");
        immersive.value = true;
    }
}

function exitImmersive() {
    console.log("exitImmersive");
    immersive.value = false;
    clearTimeout(immersiveTimeout.value);
    immersiveTimeout.value = setTimeout(enterImmersive, 3000);
}

function onVideoDidPlay() {
    videoPlayTimeout.value = setTimeout(enterImmersive, 3000);
}

function onVideoDidPause() {
    exitImmersive();
}

function onVideoEnd() {}

watchThrottled(
    currentTime,
    () => {
        http.post("/playHistories", {
            seriesId: props.series?.id,
            episodeId: props.episode?.id,
            duration: currentTime.value,
        });
    },
    { throttle: 3000 }
);
</script>
<style lang="less" scoped>
.mask-info {
    .tool-bar {
        padding-top: var(--ion-safe-area-top);
    }
    .title-info {
        margin-bottom: 16px;
        margin-bottom: env(safe-area-inset-bottom, 16px);
    }
}

.progress-bar {
    .loading {
        margin: auto;
        animation: loading 0.5s linear infinite;
    }
}

@keyframes loading {
    0% {
        width: 0;
    }
    100% {
        width: 100%;
    }
}

.progress-bar-large {
    .progress {
        position: relative;
        &::after {
            content: "";
            position: absolute;
            width: 12px;
            height: 12px;
            right: -6px;
            top: -2px;
            background: white;
            z-index: 1;
            border-radius: 6px;
        }
    }
}
ion-modal {
    --height: 50vh;
}
.episode-btn.active {
    background: var(--ion-color-tertiary);
    color: white;
}
.pay-modal {
    --height: 460px;
}
.fade-enter-active,
.fade-leave-active {
    transition: opacity 0.3s;
}

.fade-enter-from,
.fade-leave-to {
    opacity: 0;
}
</style>
