<template>
  <div
    class="long-image"
    @mousedown="onMouseDown"
    @mousemove="onMouseMove"
    @mouseup="onMouseUp"
    @mouseleave="onMouseLeave"
    @touchstart.passive="onTouchStart"
    @touchmove.prevent="onTouchMove"
    @touchend="onTouchEnd"
    @touchcancel="onTouchCancel"
    @wheel.passive="onWheel"
  >
    <audio
      ref="bgAudio$"
      loop
      autoplay
      :src="bgAudio"
      @play="bgAudioStatus = true"
      @pause="bgAudioStatus = false"
    />

    <div ref="longref$">
      <component
        class="time-item"
        v-for="(timeItem, index) in timeList"
        :key="timeItem.id"
        :is="timeItem.component"
        :info="{ ...timeItem.info, id: timeItem.id }"
        :style="{
          left: `calc(${itemW}${$isMobile ? 'vw' : 'vh'} * ${index} - ${translateLength}px)`,
          width: `${itemW}${$isMobile ? 'vw' : 'vh'}`,
          maxWidth: `${itemW}${isMobile ? 'vw' : 'vh'}`,
        }"
        @onClickTimeItem="onClickTimeItem"
      />
    </div>

    <Interaction ref="interaction$" :currentTimeIdx="currentTimeIdx" :list="timeList" />


    <Vmenu
      :currentTimeIdx="currentTimeIdx"
      @onClickMenuItem="onClickMenuItem"
      @onClickTimeItem="onClickTimeItem"
      :list="timeList"
      :bgAudioStatus="bgAudioStatus"
    />


    <teleport to="body">

      <Transition>
        <div v-if="isLongImageVideo" class="fade-in-video-wrap">
          <button class="skip-button" v-if="isShowSkip" @click="onSkipClick">
            <img :src="skipImg" alt="" draggable="false">
          </button>

          <button
            class="bofang-button"
            @click="onVideoCanPlayThrough"
            v-if="isNeedToBofang"
          >
            <img :src="bofangImg" alt="" draggable="false">
          </button>
          <video
            ref="video$"
            muted
            autoplay
            :poster="videoPostImg"
            class="initial-video"
            playsinline="true"
            x5-playsinline="true"
            webkit-playsinline="true"
            :src="`${config.cdnDir}videos/video2.mp4`"
            @playing="isNeedToBofang = false"
            @ended="onFadeInVideoEnd"
            @mousedown.passive.stop
            @touchstart.passive.stop
            @canplaythrough="onVideoCanPlayThrough"
            @wheel.passive.stop
          />
        </div>
      </Transition>

      <Transition>
        <div v-if="isShowDir">
          <Directory @close="isShowDir = false" />
        </div>
      </Transition>

      <Transition>
        <div class="guide" v-if="isShowGuide">
          <img :src="guideImg" alt="" draggable="false">
          <div class="tips">
            <p>滚动鼠标滚轮，浏览更多内容</p>
            <img :src="mouseImg" alt="" draggable="false">
            <div @click="onCloseGuide">
              <img :src="comfirImg" alt="" draggable="false">
            </div>
          </div>
        </div>
      </Transition>

      <div v-if="store.currentHotspot">
        <Hotspot @close="store.currentHotspot = ''" />
      </div>
    </teleport>

  </div>
</template>

<script setup>

import { ref, getCurrentInstance, watch, computed, onMounted } from "vue"
import appStore from "@/store/index";
import timeList from "@/data/index";
import Vmenu from "@/components/menu.vue"
import Directory from "@/components/directory.vue"
import Hotspot from "@/components/Hotspot.vue"
import Interaction from "@/components/Interaction.vue"
import { useRouter } from "vue-router"

const router = useRouter()
const store = appStore();


const isMouseDown = ref(false);
const lastMoveEventTimeStamp = ref(0);
const moveSpeed = ref(0);
const lastTouchPos = ref(0);
const maxTranslateLength = ref(0);

const guideImg = utils.getImageUrl(`guide.jpg`)
const mouseImg = utils.getImageUrl(`mouse.png`)
const comfirImg = utils.getImageUrl(`btn_concern.png`)
const skipImg = utils.getImageUrl(`skip.png`)
const bofangImg = utils.getImageUrl(`bofang.png`)

const longref$ = ref(null)
const video$ = ref(null)
const interaction$ = ref(null)

// 背景音乐相关
const bgAudio = utils.getAudioUrl('bg.mp3')
const bgAudio$ = ref(null)
onMounted(() => {
  bgAudio$.value.volume = 0.2
})
const bgAudioStatus = ref(false)
function switchBgAudio() {
  if (bgAudio$.value.paused) {
    bgAudio$.value.play()
  } else {
    bgAudio$.value.pause()
  }
}

// 过渡视频相关
const videoPostImg = utils.getImageUrl(`videobg.jpg`)
const isLongImageVideo = ref(true)
const isNeedToBofang = ref(true)
const isShowSkip = ref(false)
const onVideoCanPlayThrough = () => {
  if (video$.value) {
    video$.value.play()
    isNeedToBofang.value = false
  }
}
const onSkipClick = () => {
  isShowGuide.value = true
  setTimeout(() => {
    isLongImageVideo.value = false
  }, 100);
}
function onFadeInVideoEnd() {
  isShowGuide.value = true
  setTimeout(() => {
    isLongImageVideo.value = false
  }, 100);
}

// 动画帧相关
const lastAnimationTimeStamp = ref(0);
const animationFrameId = ref(0);

// 镜头平移相关
const translateLength = ref(0);

const currentTimeIdx = ref(0);

const instance = getCurrentInstance()
const globalProperties = instance.appContext.app.config.globalProperties

const itemW = computed(() => 280)

const isShowDir = ref(false)
const isShowGuide = ref(false)

let firstIn = true
const onCloseGuide = () => {
  isShowGuide.value = false
  if (firstIn) {
    firstIn = false
    interaction$.value.handleShow()
    store.canPlayLongImageBgAudio = true
  }
}

const animationFrameTask = () => {
  const timeStamp = Date.now()
  const timeElapsed = timeStamp - lastAnimationTimeStamp.value

  // 速度减慢
  if (moveSpeed.value > 0) {
    moveSpeed.value -= (globalProperties.$isMobile ? 0.001 : 0.003) * timeElapsed
    if (moveSpeed.value < 0) {
      moveSpeed.value = 0
    }
  } else if (moveSpeed.value < 0) {
    moveSpeed.value += (globalProperties.$isMobile ? 0.001 : 0.003) * timeElapsed
    if (moveSpeed.value > 0) {
      moveSpeed.value = 0
    }
  }

  // 根据速度更新距离
  if (store.canMoveCamera) {
    translateLength.value += moveSpeed.value * timeElapsed
    if (translateLength.value < 0) {
      translateLength.value = 0
    } else if (translateLength.value > maxTranslateLength.value) {
      translateLength.value = maxTranslateLength.value
      moveSpeed.value = 0
    }
  }

  lastAnimationTimeStamp.value = timeStamp
  animationFrameId.value = requestAnimationFrame(animationFrameTask)
}


const onClickTimeItem = (index) => {
  translateLength.value = longref$.value.children[0].offsetWidth * index
  console.log('result:', longref$.value.children[0].offsetWidth * index);
}

const onClickMenuItem = (item) => {
  if (item.id === 'bgAudio') {
    switchBgAudio()
  } else if (item.id === 'search') {
    isShowDir.value = true
  } else if (item.id === 'tip') {
    isShowGuide.value = true
  } else if (item.id === 'home') {
    router.push({ path: '/' })
  }
}

const calcTranslateLimit = () => {
  maxTranslateLength.value = longref$.value.children[0].offsetWidth * (timeList.length - 1)
}

const onMouseDown = () => {
  isMouseDown.value = true
  moveSpeed.value = 0
  lastMoveEventTimeStamp.value = 0
  lastAnimationTimeStamp.value = Date.now()
}


const onMouseMove = (e) => {
  if (isMouseDown.value) {
    // 有些pc端浏览器比如firefox会有两次事件时间戳相同的情况发生。
    if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
      // 更新speed
      const currentMoveSpeed = - e.movementX / (e.timeStamp - lastMoveEventTimeStamp.value)
      moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
    }
    lastMoveEventTimeStamp.value = e.timeStamp
  }
}

const onMouseUp = () => {
  isMouseDown.value = false
}

const onMouseLeave = () => {
  isMouseDown.value = false
}

const onTouchStart = (e) => {
  isMouseDown.value = true
  moveSpeed.value = 0
  lastMoveEventTimeStamp.value = 0
  lastAnimationTimeStamp.value = Date.now()
  lastTouchPos.value = (globalProperties.$isRotate ? e.changedTouches[0].clientY : e.changedTouches[0].clientX)
}


const onTouchMove = (e) => {
  if (isMouseDown.value && e.changedTouches.length === 1) {
    // 疯狂操作的极端情况下两个时间戳之间的时差会不合理，甚至为0
    if (lastMoveEventTimeStamp.value && (e.timeStamp - lastMoveEventTimeStamp.value > 1)) {
      // 更新speed
      const currentMoveSpeed = - ((globalProperties.$isRotate ? e.changedTouches[0].clientY : e.changedTouches[0].clientX) - lastTouchPos.value) / (e.timeStamp - lastMoveEventTimeStamp.value) * (globalProperties.$isFirefox ? 2.2 : 1.5)
      moveSpeed.value = moveSpeed.value * 0.9 + currentMoveSpeed * 0.1
      lastTouchPos.value = globalProperties.$isRotate ? e.changedTouches[0].clientY : e.changedTouches[0].clientX
    }
    lastMoveEventTimeStamp.value = e.timeStamp
  }
}


const onTouchEnd = () => {
  isMouseDown.value = false
}


const onTouchCancel = () => {
  isMouseDown.value = false
}


const onWheel = (e) => {
  if (store.canMoveCamera) {
    translateLength.value += e.deltaY
    if (translateLength.value < 0) {
      translateLength.value = 0
    } else if (translateLength.value > maxTranslateLength.value) {
      translateLength.value = maxTranslateLength.value
      moveSpeed.value = 0
    }
  }
}

watch(translateLength, (vNew) => {
  try {
    currentTimeIdx.value = Math.round(translateLength.value / longref$.value.children[0].offsetWidth)
  } catch (error) {
    console.error('translateLength error: ', error)
  }
})

onMounted(() => {
  animationFrameId.value = requestAnimationFrame(animationFrameTask)

  if (store.longImageTranslateLengthRecord) {
    translateLength.value = store.longImageTranslateLengthRecord
    store.longImageTranslateLengthRecord = null
  }
  calcTranslateLimit()
  window.addEventListener('resize', calcTranslateLimit)

  setTimeout(() => {
    isShowSkip.value = true
  }, 6000);
})




</script>

<style lang="scss" scoped>
.long-image {
  height: 100%;
  width: 100%;
  position: relative;
  overflow: hidden;

  .time-item {
    position: absolute;
    top: 0;
    height: 100%;
    text-align: center;
    justify-content: flex-start;
    display: flex;
    align-items: center;
  }
}

.guide {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 99;
  background-color: rgba($color: #000000, $alpha: 0.65);
  backdrop-filter: blur(15px);
  display: flex;
  justify-content: center;
  align-items: flex-end;

  >img {
    width: 100%;
  }

  .tips {
    position: absolute;
    top: 25%;
    left: 50%;
    transform: translateX(-50%);
    z-index: 100;
    text-align: center;
    color: #fff;
    width: 20%;

    >img {
      margin: 1.63rem 0 1rem;
      width: 80%;
    }

    >div {
      cursor: pointer;

      >img {
        width: 7rem;
      }
    }
  }
}


.fade-in-video-wrap {
  .skip-button {
    position: absolute;
    top: 1.21rem;
    right: 1.46rem;
    height: 1.75rem;
    z-index: 10000;

    img {
      height: 100%;
    }
  }

  .bofang-button {
    position: absolute;
    left: 50%;
    bottom: 30%;
    transform: translateX(-50%);
    z-index: 10000;
    width: 6rem;

    img {
      width: 100%;
    }
  }

  .initial-video {
    position: absolute; // 微信内嵌浏览器里视频必须决定对定位且z-index为负，否则，开始播放后，应该层叠在其上的决对定位的元素不会显示。
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #1f0f05;
    object-fit: cover;
  }
}
</style>