<template>
  <div class="document-editor-container" ref="docEditorContainer">
    <!-- 编辑工具 -->
    <div class="tools-container" :class="{ mobile: isMobileDevice }">
      <Button :class="{ 'with-text': !isMobileDevice }" @click="openInsertPageDialog">
        <InsertPage />
        <span>{{ $t('documentEditor.insert') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length || selectedPageList.length == pageList.length  }" @click="openDeletePageDialog">
        <DeletePage />
        <span>{{ $t('documentEditor.delete') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="rotatePage(1)">
        <RotatePageRight />
        <span>{{ $t('documentEditor.rotateRight') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="rotatePage(-1)">
        <RotatePageLeft />
        <span>{{ $t('documentEditor.rotateLeft') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="copyPage">
        <CopyPage />
        <span>{{ $t('documentEditor.copy') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="openExtractPageDialog">
        <ExtractPage />
        <span>{{ $t('documentEditor.extract') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="replacePage">
        <ReplacePage />
        <span>{{ $t('documentEditor.replace') }}</span>
      </Button>
      <Button :class="{ 'with-text': !isMobileDevice, disabled: !selectedPageList.length }" @click="openMovePageDialog">
        <MovePage />
        <span>{{ $t('documentEditor.move') }}</span>
      </Button>
      <Button class="select-all" @click="selectAll">
        <UnselectAll v-if="selectedPageList.length === pageList.length" />
        <SelectAll v-else />
      </Button>
    </div>

    <!-- 页面展示 -->
    <div class="page-container" ref="dragContainer" :style="{ 'margin-left': marginLeft + 'px' }">
      <div v-for="(item, index) in pageList" :key="`${item.type} - ${index}`" class="page"
        :class="{
          'selected': selectedPageList.includes(index),
          'drag-indicate-right': dragToIndex === index && !isDragToLeft,
          'drag-indicate-left': dragToIndex + 1 === index && isDragToLeft,
          'drag-indicate-disable': dragFromIndex >= 0 && dragToIndex >= -1 && dragIndicateDisable(index),
          'has-hover': !isMobileDevice && dragFromIndex < 0 && !selectedPageList.includes(index)
        }"
        ref="imgBoxEl"
      >
        <div class="img-box" @click="selectPage(index)">
          <img v-if="item.img" :src="item.img" :style="`transform: rotate(${rotationToAngle(item.rotation)}deg);`" />
          <div v-else-if="item.type === 'blank'"
            :class="{ 'blank-page': item.type === 'blank' }"
            :style="{ 'transform': 'rotate(' + rotationToAngle(item.rotation) + 'deg)', 'width': blankPageScaleSize(item.size).width + 'px', 'height': blankPageScaleSize(item.size).height + 'px' }">
          </div>
        </div>
        <p>{{ index + 1 }}</p>
      </div>
    </div>

  </div>
  <InsertPageSettingDialog @insertPage="handleInsertPage" :selectedPageList="selectedPageList" :totalPages="pageList.length" />
  <DeletePageDialog @deletePage="handleDeletePage" :selectedPageList="selectedPageList" />
  <ExtractPageSettingDialog @extractPage="handleExtractPage" :totalPages="pageList.length" :selectedPageList="selectedPageList" />
  <MovePageSettingDialog @movePage="handleMovePage" :totalPages="pageList.length" :selectedPageList="selectedPageList" />
</template>

<script setup>
import { ref, onMounted, reactive, onUnmounted, computed } from 'vue'
import { useViewerStore } from '@/stores/modules/viewer'
import { useDocumentStore } from '@/stores/modules/document'
import core from '@/core'
import { isMobileDevice } from '@/helpers/device'

const { Sortable } = defineProps(['Sortable'])

const useViewer = useViewerStore()
const useDocument = useDocumentStore()

const data = reactive({
  pageList: [], // 展示的所有页面
  selectedPageList: [], // 选中的页面index列表
})
let { pageList, selectedPageList } = data

const dragContainer = ref(null)
const dragFromIndex = ref(-2)
const dragToIndex = ref(-2)
const isDragToLeft = ref(false)
const imgBoxEl = ref(null)
const marginLeft = ref(0)
const docEditorContainer = ref(null)

const ratio = window.devicePixelRatio || 1
const isMobileWidth = window.innerWidth < 768
let timer = null

onMounted(() => {
  Sortable.create(dragContainer.value, {
    multiDrag: true,
    selectedClass: 'sortable-selected',
    // handle: '.img-box',
    dragClass: "sortable-drag",
    sort: false,
    forceFallback: true,
    fallbackTolerance: isMobileDevice ? 0 : 20,
    onStart: dragStart,
    onEnd: dragEnd,
    delay: isMobileDevice ? 200 : 0
  })

  const { width, height } = imgBoxEl.value[0].getBoundingClientRect()
  const pageSize = {
    width,
    height
  }
  core.getDocEditorPages(pageSize)

  window.addEventListener('resize', updateMarginLeft)
  updateMarginLeft()
})

onUnmounted(() => {
  core.removeEvent('getDocEditorPages', getPages)
  window.addEventListener('resize', updateMarginLeft)
})

// 初始化 获取所有页面数量和序号
const totalPages = core.getPagesCount()
for (let i = 0; i < totalPages; i++) {
  pageList.push({
    type: 'page'
  })
}

// 获取单个页面图片
const getPages = (data) => {
  const { index, pageData } = data
  pageList[index] = pageData
}
core.addEvent('getDocEditorPages', getPages)

// 打开插入页面选项弹窗
const openDeletePageDialog = () => {
  useViewer.openElement('deletePageDialog')
}

// 插入页面
const handleInsertPage = async (data) => {
  const operation = {
    type: 'insert',
    pageIndex: data.place
  }
  
  if (data.type === 'blank') {
    // 添加数据到用于展示的pageList
    const adjacentPage = data.targetPlace ? pageList[data.place - 1] : (pageList[data.place] || pageList[data.place - 1])
    const pageListData = {
      type: data.type,
      rotation: 0,
      size: data.size || {
        width: adjacentPage.size.width,
        height: adjacentPage.size.height
      }
    }
    pageList.splice(data.place, 0, pageListData)

    // 要传到core处理的数据
    operation.size = pageListData.size
    core.saveDocumentEdit(operation)

  } else if (data.type === 'pdf') {
    operation.file = data.file
    operation.range = data.range
    operation.password = data.password || ''
    
    const { width, height } = imgBoxEl.value[0].getBoundingClientRect()

    const totalPages = await core.saveDocumentEdit(operation)
    if (!totalPages) return
    const oldLenth = pageList.length
    for (let i = 0; i < totalPages - oldLenth; i++) {
      pageList.splice(data.place + i, 0, { type: 'page' })
    }

    const pageSize = {
      width,
      height
    }
    core.getDocEditorPages(pageSize, data.place, totalPages - oldLenth)
  }
  useDocument.setDocEditorOperationList(operation)
  selectedPageList.length = 0
}

// 计算空白页的显示大小
const blankPageScaleSize = (size) => {
  const { width, height } = size
  const boxWidth = isMobileWidth ? 140 : 204
  const boxHeight = isMobileWidth ? 141 : 216

  const scaleWidth = width / ratio
  const scaleHeight = height / ratio

  const widthRatio = boxWidth / scaleWidth
  const heightRatio = boxHeight / scaleHeight

  let scaleRatio = Math.min(widthRatio, heightRatio)

  if (scaleRatio > 1) {
    scaleRatio = 1
  }

  const scaledWidth = scaleWidth * scaleRatio
  const scaledHeight = scaleHeight * scaleRatio

  return { width: scaledWidth, height: scaledHeight}
}

// 选中页面
const selectPage = (index) => {
  const i = selectedPageList.indexOf(index)
  i === -1 ? selectedPageList.push(index) : selectedPageList.splice(i, 1)
}

// 全选
const selectAll = () => {
  if (selectedPageList.length < pageList.length) {
    selectedPageList.length = 0
    for (let i = 0; i < pageList.length; i++) {
      selectedPageList.push(i)
    }
  } else {
    selectedPageList.length = 0
  }
}

// 打开删除页面弹窗
const openInsertPageDialog = () => {
  useViewer.openElement('insertPageSettingDialog')
}

// 删除页面
const handleDeletePage = () => {
  selectedPageList.sort((a, b) => b - a)
  selectedPageList.forEach(index => {
    pageList.splice(index, 1)
  })

  const operation = {
    type: 'delete',
    selectedPageIndexArray: Array.from(selectedPageList)
  }
  core.saveDocumentEdit(operation)
  useDocument.setDocEditorOperationList(operation)
  selectedPageList.length = 0
}

// 旋转页面
const rotatePage = (rotation) => {
  selectedPageList.forEach(index => {
    const page = pageList[index]
    page.rotation += rotation
    if (page.rotation > 3 || page.rotation < -3) page.rotation = 0
  })

  const operation = {
    type: 'rotate',
    selectedPageIndexArray: Array.from(selectedPageList),
    rotation
  }
  core.saveDocumentEdit(operation)
  useDocument.setDocEditorOperationList(operation)
}
// 旋转角度值（为：-3,-2,-1,0,1,2,3）（0是0度，1是90度，2是180度，3是270度）
const rotationToAngle = (rotation) => {
  const map = new Map([[-3, -270], [-2, 180], [-1, -90], [0, 0], [1, 90], [2, 180], [3, 270]])
  return map.get(rotation)
}

// 复制页面
const copyPage = () => {
  selectedPageList.sort((a, b) => b - a)
  selectedPageList.forEach(index => {
    pageList.splice(index, 0, { ...pageList[index] })
  })

  const operation = {
    type: 'copy',
    selectedPageIndexArray: Array.from(selectedPageList)
  }
  core.saveDocumentEdit(operation)
  useDocument.setDocEditorOperationList(operation)
  selectedPageList.length = 0
}

// 替换页面
const replacePage = () => {
  const fileInput = document.createElement('input')
  fileInput.type = 'file'
  fileInput.accept = '.pdf'
  fileInput.click()

  fileInput.addEventListener('change', async function(event) {
    const file = event.target.files[0]
    const startIndex = selectedPageList[0]

    let url = URL.createObjectURL(file)
    const pass = await core.checkPassword(url, true)
    if (pass === false) return

    handleInsertPage({
      type: 'pdf',
      file,
      range: 'all',
      place: startIndex,
      password: pass
    })
    handleDeletePage()
  })
}

// 打开提取页面弹窗
const openExtractPageDialog = () => {
  useViewer.openElement('extractPageSettingDialog')
}

// 提取页面
const handleExtractPage = async (data) => {
  let exportRange = data.range.replace(/\s/g, '')
  const pagesCount = pageList.length
  if (data.range === 'all') {
    exportRange = '1-' + pagesCount
    // exportRange = ''
  } else if (data.range === 'odd') {
    exportRange = Array.from({ length: pagesCount }, (_, i) => i + 1).filter(num => num % 2 !== 0).join(",")
  } else if (data.range === 'even') {
    exportRange = Array.from({ length: pagesCount }, (_, i) => i + 1).filter(num => num % 2 === 0).join(",")
  }

  let parts = exportRange.split(',')
  let indexArray = []

  parts.forEach(part => {
    if (part.includes('-')) {
      let [start, end] = part.split('-').map(num => parseInt(num))
      for (let i = start; i <= end; i++) {
        indexArray.push(i - 1)
      }
    } else if (part) {
      indexArray.push(parseInt(part) - 1)
    }
  })

  const operation = {
    type: 'extract',
    range: data.separateFile ? indexArray : exportRange,
    separateFile: data.separateFile
  }
  await core.saveDocumentEdit(operation)
  useDocument.setDocEditorOperationList(operation)

  if (data.deleteAfter) {
    indexArray.reverse().forEach(index => {
      pageList.splice(index, 1)
    })

    const operation = {
      type: 'delete',
      selectedPageIndexArray: indexArray
    }
    core.saveDocumentEdit(operation)
    useDocument.setDocEditorOperationList(operation)
    selectedPageList.length = 0
  }
}

// 打开移动页面弹窗
const openMovePageDialog = () => {
  useViewer.openElement('movePageSettingDialog')
}

// 移动页面
const handleMovePage = (targetIndex) => {
  if (selectedPageList.length === 1 ||
    (selectedPageList.length < 2 && dragFromIndex.value >= 0) ||
    (selectedPageList.length > 1 && dragFromIndex.value >= 0 && !selectedPageList.includes(dragFromIndex.value))
  ) { // 移动一页
    const dragSelectedOrNoDrag = (selectedPageList.length === 1 && selectedPageList.includes(dragFromIndex.value)) || (selectedPageList.length === 1 && dragFromIndex.value < 0)
    const index = dragSelectedOrNoDrag ? selectedPageList[0] : [dragFromIndex.value]
    const tIndex = index > targetIndex ? targetIndex : targetIndex - 1
    if (index === tIndex) return
    
    const [page] = pageList.splice(index, 1)
    pageList.splice(tIndex, 0, page)

    const operation = {
      type: 'move',
      pageIndex: index,
      targetPageIndex: tIndex
    }
    core.saveDocumentEdit(operation)
    useDocument.setDocEditorOperationList(operation)
    if (dragSelectedOrNoDrag) selectedPageList[0] = tIndex

  } else { // 移动多页
    selectedPageList.sort((a, b) => a - b)

    for (let i = 0; i < selectedPageList.length; i++) {
      let index, tIndex
      if (selectedPageList[i] === targetIndex) {
        index = selectedPageList[i]
        tIndex = targetIndex
      } else if (selectedPageList[i] > targetIndex) {
        index = selectedPageList[i]
        if (selectedPageList.includes(targetIndex)) {
          tIndex = targetIndex
          for (let j = 0; j < selectedPageList.length; j++) {
            if (selectedPageList[j] === tIndex && index !== tIndex) tIndex++
          }
        } else {
          tIndex = targetIndex
        }
      } else {
        index = selectedPageList[i] - i
        tIndex = targetIndex - 1
      }

      if (selectedPageList.includes(index) && selectedPageList.includes(tIndex) && index === tIndex) continue

      const [page] = pageList.splice(index, 1)
      pageList.splice(tIndex, 0, page)

      const operation = {
        type: 'move',
        pageIndex: index,
        targetPageIndex: tIndex
      }
      core.saveDocumentEdit(operation)
      useDocument.setDocEditorOperationList(operation)
      selectedPageList[i] = selectedPageList[i] > targetIndex ? tIndex : tIndex - i
    }
  }
}

// 拖拽开始
const dragStart = (e) => {
  dragFromIndex.value = e.oldIndex
  dragContainer.value.addEventListener(isMobileDevice ? 'touchmove' : 'mousemove', dragging)

  if (isMobileDevice) {
    document.body.style.overscrollBehavior = 'none'
    document.body.style.userSelect = 'none'
    document.getElementById('app').style.touchAction = 'none'
    docEditorContainer.value.style.overflow = 'hidden'
  }
}

// 拖拽中
const dragging = (e) => {
  if (selectedPageList.length > 1 && selectedPageList.includes(dragFromIndex.value)) {
    dragContainer.value.querySelector('.sortable-drag').style.setProperty("--after-content", "'" + selectedPageList.length + "'")
  }

  let target = isMobileDevice ? document.elementFromPoint(e.touches[0].clientX, e.touches[0].clientY) : e.target
  const pageDomList = dragContainer.value.children

  for (let i = 0; i < pageDomList.length; i++) {
    const element = pageDomList[i]

    if (element.contains(target)) {
      const domRect = element.getBoundingClientRect()
      const offsetX = isMobileDevice ? (e.touches[0].clientX - domRect.left) : (e.offsetX + 30)
      isDragToLeft.value = offsetX < domRect.width / 2

      if (isDragToLeft.value) {
        dragToIndex.value = i - 1
      } else {
        dragToIndex.value = i
      }
    }
  }

  if (isMobileDevice) handleAutoScroll(e.touches[0].clientY)
}

// 拖拽结束
const dragEnd = () => {
  clearInterval(timer)
  dragContainer.value.removeEventListener(isMobileDevice ? 'touchmove' : 'mousemove', dragging)
  if (dragToIndex.value > -2 && !dragIndicateDisable(dragToIndex.value)) {
    handleMovePage(dragToIndex.value + 1)
  }
  dragFromIndex.value = -2
  dragToIndex.value = -2

  if (isMobileDevice) {
    document.body.style.overscrollBehavior = 'auto'
    document.body.style.userSelect = 'auto'
    document.getElementById('app').style.touchAction = 'auto'
    docEditorContainer.value.style.overflow = 'auto'
  }
}

// 拖拽计算显示位置的竖条是否置灰
const dragIndicateDisable = (index) => {
  if (![index - 1, index, index + 1].includes(dragToIndex.value + 1)) return false

  if (selectedPageList.includes(dragFromIndex.value)) {
    if (selectedPageList.length === 1 && (selectedPageList[0] === dragToIndex.value + 1 || selectedPageList[0] === dragToIndex.value)) return true
    if (selectedPageList.length > 1 && isConsecutive(selectedPageList) && (selectedPageList.includes(dragToIndex.value + 1) || selectedPageList.includes(dragToIndex.value))) return true
  } else {
    if ([dragFromIndex.value, dragFromIndex.value - 1].includes(dragToIndex.value)) return true
  }

  return false
}

// 是否是连续的数字
const isConsecutive = (arr) => {
  arr.sort(function(a, b) {
    return a - b
  })

  for (var i = 0; i < arr.length - 1; i++) {
    if (arr[i] + 1 !== arr[i + 1]) {
      return false
    }
  }

  return true
}

// 计算左边距
const updateMarginLeft = () => {
  const width = window.innerWidth
  const pageWidth = width > 767 ? 280 : 170
  marginLeft.value = parseInt(width % pageWidth / 2)
}

// 移动端处理自动滚动
const handleAutoScroll = (clientY) => {
  const threshold = 100
  const containerEl = docEditorContainer.value
  const containerRect = containerEl.getBoundingClientRect()
  const containerHeight = containerRect.height
  const deltaY = clientY
  const totalHeight = containerEl.scrollHeight
  
  // 判断鼠标位置是否在阈值范围内
  if (deltaY <= threshold || deltaY >= containerHeight - threshold) {
    clearInterval(timer)
    timer = setInterval(() => {
      // 向上滚动
      if (deltaY <= threshold) {
        containerEl.scrollTop -= 10
        if (containerEl.scrollTop <= 0) {
          clearInterval(timer)
        }
      }
      // 向下滚动
      else if (deltaY >= containerHeight - threshold) {
        containerEl.scrollTop += 10
        if (containerEl.scrollTop + containerHeight >= totalHeight) {
          clearInterval(timer)
        }
      }
    }, 10)
  } else {
    // 鼠标位置不在阈值范围内，停止滚动
    clearInterval(timer)
  }
}
</script>

<style lang="scss">
.document-editor-container {
  margin-top: 44px;
  width: 100%;
  background-color: var(--c-doc-editor-bg);
  overflow: auto;

  .tools-container {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: -44px;
    width: 100%;
    height: 44px;
    z-index: 3;
    background-color: var(--c-toolbar-bg);
    border-bottom: 1px solid var(--c-toolbar-border);
    opacity: 1;
    overflow-x: auto;
    overflow-y: hidden;

    &.hidden {
      display: none;
    }

    button {
      &.disabled {
        opacity: 1;
        color: #999;
      }

      &:last-child {
        margin-right: 0;
      }
    }

    &.mobile .button span {
      display: none;
    }
  }

  .page-container {
    padding-bottom: 30px;
    display: flex;
    flex-flow: wrap;

    .page {
      position: relative;
      padding: 8px;
      margin: 30px 30px 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: space-between;
      width: 220px;
      height: 256px;
      cursor: pointer;

      .img-box {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: calc(100% - 24px);
        user-select: none;

        img {
          pointer-events: none;
        }

        img,
        .blank-page {
          max-width: 100%;
          max-height: 100%;
          border: 0.5px solid rgba(0, 0, 0, 0.12);
          -webkit-touch-callout: none;
          -ms-touch-action: manipulation;
          touch-action: manipulation; 
        }

        .blank-page {
          background-color: #fff;
        }
      }

      p {
        margin-top: 8px;
        font-size: 12px;
        line-height: 16px;
        color: var(--c-right-side-header-text);
        text-align: center;
        user-select: none;
      }

      &.selected {
        background-color: var(--c-header-button-active);
      }

      &.drag-indicate-right:after {
        position: absolute;
        top: 0;
        right: -32px;
        display: block;
        content: '';
        height: 100%;
        width: 4px;
        background-color: var(--c-popup-bg-active);
      }

      &.drag-indicate-left::before {
        position: absolute;
        top: 0;
        left: -32px;
        display: block;
        content: '';
        height: 100%;
        width: 4px;
        background-color: var(--c-popup-bg-active);
      }

      &.drag-indicate-disable::after, &.drag-indicate-disable::before {
        background-color: var(--c-divider);
      }

      &.sortable-drag::after {
        content: var(--after-content, '1');
        position: absolute;
        top: 10px;
        left: 10px;
        padding: 5px 20px;
        border-radius: 50px;
        background-color: var(--c-popup-bg-active);
        color: white;
      }
    }
  }
}

@media screen and (min-width: 820px) {
  .document-editor-container {
    .tools-container {
      button.select-all {
        position: absolute;
        right: 16px;
      }
    }

    .page-container .page.has-hover:hover {
      background-color: rgba(0, 0, 0, 0.10);
    }
  }
}

@media screen and (max-width: 360px) {
  .document-editor-container .tools-container {
    padding: 0 10px;
    justify-content: flex-start;
  }
}

@media screen and (min-width: 578px) {
  .document-editor-container .tools-container .button {
    &:not(.disabled):hover {
      background-color: var(--c-header-button-active);
    }
  }
}

@media screen and (max-width: 767px) {
  .document-editor-container .page-container {
    .page {
      margin: 12px 10px;
      padding: 5px;
      width: 150px;
      height: 175px;

      &.drag-indicate-right:after {
        right: -12px;
      }

      &.drag-indicate-left::before {
        left: -12px;
      }
    }
  }
}
</style>
