<template>
  <v-container fluid class="px-0">
    <div class="message-list">
      <chat-list :loader="readMore" :messages="channels.messages" />
    </div>
  </v-container>

  <v-footer
    app
    class="footer-section flex-col gap-2 min-h-[64px]"
    :style="`padding-bottom: max(${safeAreaBottom}, 6px)`"
  >
    <v-expand-transition>
      <v-expansion-panels v-show="channels.call">
        <v-expansion-panel
          eager
          icon="mdi-phone"
          title="Call is ongoing"
          elevation="1"
          class="call-expansion"
          @group:selected="(val) => val && mountJitsi()"
        >
          <template #text>
            <v-expand-transition>
              <v-progress-linear v-show="joining" indeterminate />
            </v-expand-transition>

            <div class="call-container w-full h-[360px]">
              <div id="call" class="h-full w-full" v-if="channels.call"></div>
            </div>
          </template>
        </v-expansion-panel>
      </v-expansion-panels>
    </v-expand-transition>

    <chat-editor class="w-full" @sent="scrollTop" />
  </v-footer>
</template>

<script setup lang="ts">
import { useChannels } from "@/stores/channels"
import { request } from "@/scripts/request"
import { useUI } from "@/stores/ui"
import { computed, onUnmounted, reactive, ref, watch } from "vue"
import { useRoute } from "vue-router"
import { useUserinfo } from "@/stores/userinfo"
import ChatList from "@/components/chat/ChatList.vue"
import ChatEditor from "@/components/chat/ChatEditor.vue"

const ui = useUI()
const id = useUserinfo()
const route = useRoute()
const channels = useChannels()

const safeAreaBottom = computed(() => {
  return `${ui.safeArea.bottom}px`
})

const chatList = ref<HTMLDivElement>()

const { showErrorSnackbar } = useUI()
const loading = ref(false)
const joining = ref(false)

const pagination = reactive({ page: 1, pageSize: 10, total: 0 })

async function readCall() {
  loading.value = true
  const res = await request(
    "messaging",
    `/api/channels/${route.params.channel}/calls/ongoing`
  )
  if (res.status !== 200 && res.status !== 404) {
    showErrorSnackbar(await res.text())
  } else if (res.status !== 404) {
    channels.call = await res.json()
  }
  loading.value = false
}

async function readHistory() {
  loading.value = true
  const res = await request(
    "messaging",
    `/api/channels/${route.params.channel}/messages?` + new URLSearchParams({
      take: pagination.pageSize.toString(),
      offset: ((pagination.page - 1) * pagination.pageSize).toString()
    })
  )
  if (res.status !== 200) {
    showErrorSnackbar(await res.text())
    throw new Error()
  } else {
    const data = await res.json()
    pagination.total = data["count"]
    channels.messages.push(...(data["data"] ?? []))
  }
  loading.value = false
}

async function readMore({ done }: any) {
  // Reach the end of data
  if (pagination.total === 0) {
    done("ok")
    return
  }
  if (pagination.total <= pagination.page * pagination.pageSize) {
    done("empty")
    return
  }

  pagination.page++

  try {
    await readHistory()
  } catch {
    done("error")
  }

  if (pagination.total > 0) done("ok")
  else done("empty")
}

watch(
  () => channels.current,
  (val) => {
    if (val) {
      unmountJitsi()
      pagination.page = 1
      pagination.total = 0
      readHistory()
      readCall()
    }
  },
  { immediate: true }
)

function scrollTop() {
  window.scroll({ top: 0 })
}

watch(
  () => channels.call,
  (val) => {
    if (!val) {
      if (jitsiInstance) {
        jitsiInstance.executeCommand("endConference")
        jitsiInstance.executeCommand("hangup")
      }
      unmountJitsi()
    }
  }
)

let mounted = false
let jitsiInstance: any

async function mountJitsi() {
  if (mounted) return false
  if (!channels.call) return

  joining.value = true
  const tk = await channels.exchangeCallToken()
  joining.value = false
  if (!tk) return

  const domain = tk.endpoint.replace("http://", "").replace("https://", "")
  const options = {
    roomName: channels.call.external_id,
    parentNode: document.querySelector("#call"),
    jwt: tk.token,
    userInfo: {
      avatar: id.userinfo.data?.picture,
      displayName: id.userinfo.displayName
    },
    configOverwrite: {
      prejoinPageEnabled: true,
      startWithAudioMuted: false,
      startWithVideoMuted: true
    }
  }
  // This class imported by the script tag in index.html
  // @ts-ignore
  jitsiInstance = new JitsiMeetExternalAPI(domain, options)
  mounted = true
}

function unmountJitsi() {
  mounted = false
  if (jitsiInstance) {
    jitsiInstance.dispose()
    jitsiInstance = null
  }
}

onUnmounted(() => unmountJitsi())
</script>

<style scoped>
.footer-section {
  background: rgba(255, 255, 255, 0.65);
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  border: 1px solid rgba(255, 255, 255, 0.3);

  padding-top: 8px !important;
  padding-left: 8px !important;
  padding-right: 8px !important;

  display: flex;
  justify-content: center;
}
</style>

<style>
.call-expansion .v-expansion-panel-text__wrapper {
  padding: 0 !important;
}
</style>