<template>
  <main class="entry-page">
    <section :style="{ width: `${mapWidth}px` }" class="section-viewer">
      <vue-draggable-resizable
        :style="{ width: `${mapWidth}px` }"
        :w="mapWidth"
        :h="windowHeight"
        :max-width="windowWidth"
        :handles="['mr']"
        :draggable="false"
        class-name-active="resize-active-map"
        class-name-handle="resize-handle-map"
        @resizing="onResizeMap"
      >
        <Viewer
          v-if="collectionBbox.length"
          :fetch-options="{
            fetchOptions: {
              credentials: 'include'
            }
          }"
          :geovisio-viewer="false"
          :user-id="getUserId"
          :bbox="collectionBbox"
          ref="viewerRef"
        />
      </vue-draggable-resizable>
    </section>
    <section
      :style="{ width: `${listWidth}px` }"
      class="section-sequence"
      @scroll="handleScroll"
    >
      <h1 id="sequenceTitle" class="sequences-title">
        {{ $t('pages.sequences.title') }}
      </h1>
      <div
        ref="headerList"
        :class="['sequence-item sequence-item-head', headerListClass]"
        :style="{ width: `${listWidth}px`, borderRadius: '0px' }"
      >
        <div class="sequence-header-item"></div>
        <div class="sequence-header-item">
          <span>{{ $t('pages.sequences.sequence_name') }}</span>
        </div>
        <div class="sequence-header-item">
          <span>{{ $t('pages.sequences.sequence_photos') }}</span>
        </div>
        <div class="sequence-header-item">
          <Button
            :text="$t('pages.sequences.sequence_date')"
            look="link--grey"
            icon="bi bi-arrow-down-up"
            data-test="button-sort-date"
            @trigger="sortList('datetime')"
          />
        </div>
        <div class="sequence-header-item">
          <Button
            :text="$t('pages.sequences.sequence_creation')"
            look="link--grey"
            icon="bi bi-arrow-down-up"
            data-test="button-sort-date"
            @trigger="sortList('created')"
          />
        </div>
        <div class="sequence-header-item">
          <span>{{ $t('pages.sequences.sequence_status') }}</span>
        </div>
      </div>
      <ul v-if="!isLoading" ref="list" class="sequence-list">
        <li
          v-if="userSequences.length"
          v-for="item in userSequences"
          :class="[
            'sequence-item',
            item.id === seqId ? 'button-item-hover' : ''
          ]"
          @mouseover="goToSequence(item)"
        >
          <router-link
            class="button-item"
            :to="{
              name: 'sequence',
              params: { id: item.id }
            }"
            @mouseover.stop
          >
            <div class="wrapper-thumb">
              <img
                v-if="item['stats:items'].count > 0"
                loading="lazy"
                :src="`${item.href}/thumb.jpg`"
                alt=""
                class="thumb"
              />
              <div class="wrapper-thumb-hover">
                <img
                  v-if="item['stats:items'].count > 0"
                  loading="lazy"
                  :src="`${item.href}/thumb.jpg`"
                  alt=""
                  class="thumb-hover"
                />
              </div>
            </div>
            <div>
              <span>
                {{ item.title }}
              </span>
            </div>
            <div>
              <i class="bi bi-images"></i>
              <span>
                {{ item['stats:items'].count }}
              </span>
            </div>
            <div>
              <span>
                {{
                  formatDate(
                    item.extent.temporal.interval[0][0],
                    'Do MMMM YYYY HH:mm:ss'
                  )
                }}
              </span>
            </div>
            <div>
              <span>
                {{ formatDate(item.created, 'Do MMMM YYYY HH:mm:ss') }}
              </span>
            </div>
            <div>
              <span :class="item['geovisio:status']">{{
                sequenceStatus(item['geovisio:status'])
              }}</span>
            </div>
          </router-link>
          <div class="wrapper-button">
            <Button
              :tooltip="$t('pages.sequence.hide_sequence_tooltip')"
              look="button--white background-white"
              :icon="
                item['geovisio:status'] === 'ready'
                  ? 'bi bi-eye-slash'
                  : 'bi bi-eye'
              "
              class="disable-button"
              @trigger="patchCollection(item)"
            />
            <Button
              :tooltip="$t('pages.sequence.delete_sequence_tooltip')"
              look="button--red background-white"
              icon="bi bi-trash"
              @trigger="deleteCollection(item)"
            />
          </div>
        </li>
        <div v-else class="no-sequence">
          <p class="no-sequence-text">
            {{ $t('pages.sequences.no_sequences_text') }}
          </p>
          <Link
            :text="$t('general.header.upload_text')"
            look="button button--blue"
            :route="{ name: 'why-contribute' }"
          />
        </div>
      </ul>
      <div v-else class="loader">
        <Loader look="sm" :is-loaded="false" />
      </div>
      <div class="entry-pagination">
        <Pagination
          v-for="item in paginationLinks"
          :type="item.rel"
          :href="item.href"
          :self-link="selfLink[0]"
          @trigger="goToNextPage"
        />
      </div>
      <Toast :text="toastText" :look="toastLook" @trigger="toastText = ''" />
    </section>
  </main>
</template>

<script setup lang="ts">
import { onMounted, ref, watchEffect, computed, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import { useSequenceStore } from '@/store/sequence'
import { storeToRefs } from 'pinia'
import {
  scrollIntoSelected,
  formatPaginationItems
} from '@/views/utils/sequence/index'
import { useCookies } from 'vue3-cookies'
import axios from 'axios'
import Viewer from '@/components/Viewer.vue'
import Button from '@/components/Button.vue'
import Link from '@/components/Link.vue'
import Toast from '@/components/Toast.vue'
import Loader from '@/components/Loader.vue'
import Pagination from '@/components/Pagination.vue'
import type { SequenceLinkInterface } from './interfaces/MySequencesView'
import type { ResponseUserPhotoLinksInterface } from './interfaces/MySequenceView'
import { formatDate } from '@/utils/dates'
import {
  deleteACollection,
  patchACollection
} from '@/views/utils/sequence/request'

const { t } = useI18n()
const { cookies } = useCookies()
const sequenceStore = useSequenceStore()
const { toastText, toastLook } = storeToRefs(sequenceStore)
interface PositionInterface {
  bottom: number
  top: number
  right: number
  left: number
  y: number
  x: number
}
let userSequences = ref<SequenceLinkInterface[]>([])
let paginationLinks = ref<ResponseUserPhotoLinksInterface[] | []>([])
let selfLink = ref<ResponseUserPhotoLinksInterface[] | []>([])
let collectionBbox = ref<number[]>([])
let isLoading = ref<boolean>(false)
let isSorted = ref<boolean>(false)
let seqId = ref<string>('')
let width = ref<number>(0)
let mapWidth = ref<number>(window.innerWidth / 3)
let listWidth = ref<number>(window.innerWidth / 1.5)
const windowWidth = ref<number>(window.innerWidth)
const windowHeight = ref<number>(window.innerHeight - 80)
const viewerRef = ref<any>(null)
const headerList = ref<any>(null)
const list = ref<any>(null)
const listPos = ref<PositionInterface | null>(null)
const headerLisPos = ref<PositionInterface | null>(null)

async function fetchAndFormatSequence(): Promise<void> {
  const { data } = await axios.get('api/users/me/collection')
  collectionBbox.value = data.extent.spatial.bbox[0]
  userSequences.value = getRelChild(data.links)
}

async function patchCollection(sequence: SequenceLinkInterface): Promise<void> {
  isLoading.value = true
  let visible
  if (sequence['geovisio:status'] === 'ready') visible = 'false'
  else visible = 'true'
  await patchACollection(sequence.id, visible)
  await fetchAndFormatSequence()
  viewerRef.value.viewer.reloadVectorTiles()
  isLoading.value = false
}
async function deleteCollection(
  sequence: SequenceLinkInterface
): Promise<void> {
  isLoading.value = true
  if (confirm(t('pages.sequence.confirm_sequence_dialog'))) {
    await deleteACollection(sequence.id)
    await fetchAndFormatSequence()
    viewerRef.value.viewer.reloadVectorTiles()
  }
  isLoading.value = false
}
function sequenceStatus(status: string): string {
  if (status === 'ready') return t('pages.sequences.sequence_published')
  if (status === 'hidden') return t('pages.sequences.sequence_hidden')
  return t('pages.sequences.sequence_waiting')
}
function onResizeMap(width: any): void {
  if (width) {
    width.value = width
    mapWidth.value = width.value.width
    listWidth.value = window.innerWidth - width.value.width
  }
}
const handleScroll = async () => {
  await nextTick()
  if (headerList.value && headerList.value.getBoundingClientRect()) {
    headerLisPos.value = headerList.value.getBoundingClientRect()
  }
  if (list.value && list.value.getBoundingClientRect()) {
    listPos.value = list.value.getBoundingClientRect()
  }
}
async function sortList(dateToSort: string): Promise<void> {
  isLoading.value = true
  let sortBy = `+${dateToSort}`
  if (isSorted.value) sortBy = `-${dateToSort}`
  const { data } = await axios.get(
    `api/users/me/collection?limit=50&sortby=${encodeURIComponent(sortBy)}`
  )
  selfLink.value = data.links.filter(
    (el: SequenceLinkInterface) => el.rel === 'self'
  )
  paginationLinks.value = formatPaginationItems(data.links)
  userSequences.value = getRelChild(data.links)
  isSorted.value = !isSorted.value
  scrollToElement()
  isLoading.value = false
}

function bboxIsInsideOther(mainBbox: number[], bboxInside: number[]): boolean {
  return (
    bboxInside[0] <= mainBbox[0] &&
    bboxInside[1] <= mainBbox[1] &&
    bboxInside[2] >= mainBbox[2] &&
    bboxInside[3] >= mainBbox[3]
  )
}
function goToSequence(sequence: SequenceLinkInterface): void {
  seqId.value = sequence.id
  viewerRef.value.viewer.select(seqId.value)
  const currentBbox = [
    viewerRef.value.viewer._map.getBounds()._ne.lng,
    viewerRef.value.viewer._map.getBounds()._ne.lat,
    viewerRef.value.viewer._map.getBounds()._sw.lng,
    viewerRef.value.viewer._map.getBounds()._sw.lat
  ]
  if (bboxIsInsideOther(currentBbox, sequence.extent.spatial.bbox[0])) return
  viewerRef.value.viewer._map.flyTo({
    center: [
      sequence.extent.spatial.bbox[0][0],
      sequence.extent.spatial.bbox[0][1]
    ],
    zoom: 10,
    duration: 0
  })
}
function getRelChild(
  sequences: SequenceLinkInterface[]
): SequenceLinkInterface[] {
  return sequences.filter((el: SequenceLinkInterface) => el.rel === 'child')
}
function scrollToElement(): void {
  const elementTarget = document.querySelector('#sequenceTitle')
  if (elementTarget) elementTarget.scrollIntoView({ behavior: 'smooth' })
}
async function goToNextPage(value: string): Promise<void> {
  isLoading.value = true
  const { data } = await axios.get(value)
  selfLink.value = data.links.filter(
    (el: SequenceLinkInterface) => el.rel === 'self'
  )
  paginationLinks.value = formatPaginationItems(data.links)
  userSequences.value = getRelChild(data.links)
  scrollToElement()
  isLoading.value = false
}
const getUserId = computed<string>((): string => cookies.get('user_id'))
const headerListClass = computed<string>((): string => {
  if (headerLisPos.value && listPos.value) {
    return headerLisPos.value.y != 0 && listPos.value.top < 180
      ? 'item-head-fixed'
      : ''
  }
  return ''
})
onMounted(async () => {
  isLoading.value = true
  try {
    const { data } = await axios.get('api/users/me/collection?limit=50')
    selfLink.value = data.links.filter(
      (el: SequenceLinkInterface) => el.rel === 'self'
    )
    paginationLinks.value = formatPaginationItems(data.links)
    userSequences.value = getRelChild(data.links)
    collectionBbox.value = [
      userSequences.value[0].extent.spatial.bbox[0][0],
      userSequences.value[0].extent.spatial.bbox[0][1],
      userSequences.value[0].extent.spatial.bbox[0][2],
      userSequences.value[0].extent.spatial.bbox[0][3]
    ]
    isLoading.value = false
  } catch (err) {
    isLoading.value = false
    console.log(err)
  }
})
watchEffect(() => {
  if (viewerRef.value && viewerRef.value.viewer) {
    viewerRef.value.viewer.addEventListener(
      'hover',
      (e: { detail: { seqId: string } }) => {
        seqId.value = e.detail.seqId
        scrollIntoSelected(e.detail.seqId, userSequences.value)
        viewerRef.value.viewer.select(e.detail.seqId)
      }
    )
  }
})
</script>
<style lang="scss">
.resize-handle-map-mr {
  top: 0;
  right: toRem(0);
  cursor: e-resize;
  background-color: var(--black);
  display: block !important;
}
.resize-handle-map {
  z-index: 999999;
  box-sizing: border-box;
  position: absolute;
  height: 100%;
  width: toRem(0.5);
  &:hover {
    cursor: col-resize;
  }
}
</style>
<style lang="scss" scoped>
.entry-page {
  display: flex;
  height: calc(100vh - #{toRem(8)});
  overflow: hidden;
  position: relative;
}
.section-viewer {
  height: 100%;
  position: relative;
}
.section-sequence {
  overflow-y: auto;
  overflow-x: hidden;
  height: 100%;
  position: relative;
}
.sequences-title {
  @include text(h1);
  color: var(--blue-dark);
  margin-bottom: toRem(5);
  margin-top: toRem(3);
  margin-left: toRem(3);
}
.sequence-list {
  box-shadow: 0px 2px 30px 0px #0000000f;
  padding: 0;
}
.sequence-item {
  @include text(s-regular);
  position: relative;
  border: none;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
  background-color: var(--blue-pale);
  padding: toRem(2);
  &:nth-child(2n) {
    background-color: var(--white);
  }
}
.wrapper-button {
  position: absolute;
  right: toRem(1);
  bottom: 0;
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  height: 100%;
  .button--white:first-child {
    margin-bottom: toRem(1);
  }
}
.button-item-hover {
  background-color: var(--blue);
  &:nth-child(2n) {
    background-color: var(--blue);
  }
  .button-item {
    & > *,
    & > :nth-child(2) {
      color: var(--white);
    }
  }
}
.item-head-fixed {
  position: fixed;
  top: toRem(8);
  width: 100%;
  z-index: 2;
}
.sequence-item-head {
  margin-bottom: toRem(1);
  padding: toRem(1) toRem(2);
  border-bottom: toRem(0.1) solid var(--grey);
  border-radius: toRem(2) toRem(2) 0rem 0rem;
  background-color: var(--white);
}
.sequence-item-head:hover {
  background-color: var(--white);
  color: initial;
}
.wrapper-title {
  display: flex;
  align-items: center;
}
.wrapper-thumb {
  position: relative;
}
.wrapper-thumb-hover {
  display: none;
  border-radius: toRem(0.3);
  border: toRem(1) solid var(--grey);
  position: absolute;
  bottom: 0;
  height: toRem(15);
  z-index: 1;
}
.ready {
  color: var(--green);
}
.hidden {
  color: var(--red-pale);
}
.waiting-for-process {
  color: var(--yellow);
}
.thumb-hover {
  height: 100%;
}
.wrapper-thumb:hover {
  .wrapper-thumb-hover {
    display: block;
  }
}
.thumb {
  height: 100%;
  width: 100%;
  object-fit: cover;
  border-radius: toRem(0.5);
  position: relative;
}
.button-item {
  display: flex;
  align-items: center;
  width: 100%;
  background-color: transparent;
  border: none;
  text-decoration: none;
  & > * {
    padding: toRem(1);
    text-align: initial;
    width: calc(31% - #{toRem(4.75)});
    color: var(--black);
  }
  > :first-child {
    color: var(--blue);
    width: toRem(6);
  }
  & > :first-child {
    padding: 0;
    margin-right: toRem(2);
  }
  & > :nth-child(3) {
    width: toRem(13);
  }
  & > :nth-child(2) {
    color: var(--blue-dark);
  }
}
.bi-images {
  margin-right: toRem(0.5);
}
.sequence-header-item {
  width: calc(31% - #{toRem(4.75)});
  &:first-child {
    margin-right: toRem(2);
  }
  &:first-child {
    width: toRem(6);
  }
  &:nth-child(3) {
    width: toRem(13);
  }
}
.no-sequence {
  padding-top: toRem(2);
  padding-bottom: toRem(4);
  width: fit-content;
  @include text(m-regular);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: auto;
}
.no-sequence-text {
  margin-bottom: toRem(4);
}
.loader {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}
.ay11-link {
  padding: toRem(2);
  margin-left: auto;
  width: fit-content;
}
.entry-pagination {
  margin-top: toRem(4);
  margin-bottom: toRem(4);
  width: 100%;
  display: flex;
  justify-content: center;
}
@media (max-width: toRem(102.4)) {
  .section-viewer {
    width: 30%;
  }
  .section-sequence {
    width: 70%;
  }
}
@media (max-width: toRem(76.8)) {
  .entry-page {
    padding-right: toRem(2);
    padding-left: toRem(2);
    padding-top: toRem(14);
    height: 100%;
  }
  .section-viewer {
    display: none;
  }
  .section-sequence {
    width: 100% !important;
  }
  .sequence-item-head {
    display: none;
  }
  .button-item {
    flex-direction: column;
    align-items: center;
    padding-right: toRem(1);
    padding-left: toRem(1);
    & > * {
      text-align: center;
      width: 100%;
    }
    .wrapper-thumb {
      margin-right: 0;
    }
  }
  .sequence-item {
    border-top-right-radius: toRem(1);
    border-top-left-radius: toRem(1);
    flex-direction: column;
  }
  .wrapper-button {
    flex-direction: row;
    position: relative;
    right: 0;
    bottom: 0;
    justify-content: center;
    margin-top: toRem(1);
    margin-bottom: 0;
    .button--white:first-child {
      margin-right: toRem(1);
      margin-bottom: 0;
    }
  }
}
</style>
