<template>
  <div class="pdf-container">
    <div class="header">
      <div class="title">{{ title }}</div>
      <div class="close-icon" @click="emits('close')">
        <CloseOutlined />
      </div>
    </div>
    <div ref="pdfRef" class="pdf-viewer"></div>
  </div>
</template>
<script setup>
import { CloseOutlined } from '@ant-design/icons-vue';
import { ref, watch } from 'vue';
import PdfjsWorker from 'pdfjs-dist/build/pdf.worker.js?worker';
const emits = defineEmits(['close']);
const props = defineProps({
  src: { type: String, required: true },
  content: { type: String, required: true },
  num: { type: Number, required: false }
});
const pdfRef = ref(null);
const height = ref(0);
const start = ref(0);
const pageContent = ref([]);
const pageText = ref([]);
// 侦听props的src改变，则立即切换渲染pdf
watch(
  () => props.src,
  () => {
    setTimeout(() => init(), 1);
  },
  { immediate: true }
);
const title = computed(() => {
  return window.formatDocName(decodeURI(decodeURI(props.src)))
  // return `/lib/pdfjs/web/viewer.html?file=http://121.40.148.47:8530/doc/knowledge_base/download_doc/国土资源部 国家发展和改革委员会+财政部+住房和城乡建设部农业部+中国人民银行+国家林业局+中国银行业监督管理委员会关于扩大国有土地有偿使用范围的意见%28279-283%29.pdf`
});
// 渲染pdf
async function init() {
  var pdfDom = document.getElementsByClassName('pdf-viewer')[0];
  while (pdfDom.firstChild) {
    pdfDom.removeChild(pdfDom.firstChild);
  }
  // 异步加载pdf.js
  const PDFJS = await import('pdfjs-dist/build/pdf.js');
  if (typeof window !== 'undefined' && 'Worker' in window) {
    PDFJS.GlobalWorkerOptions.workerPort = new PdfjsWorker();
  }
  // 加载文档
  let loadingTask = PDFJS.getDocument({ url: props.src });
  loadingTask.__PDFDocumentLoadingTask = true;
  pageContent.value = [];
  const pdf = await loadingTask.promise; // 使用await等待加载完毕
  // 循环渲染每一页
  for (let i = 1; i <= pdf.numPages; i++) {
    const page = await pdf.getPage(i);
    await renderPage(page, PDFJS, i);
  }
  console.log('pdf页面全部渲染完毕', pdf.numPages, pdf);
  pageText.value = [];
  //获取每页数据
  var textDivs = document.getElementsByClassName('textLayer');
  if (textDivs) {
    for (var i = 0; i < textDivs.length; i++) {
      var item = { page: i + 1, txt: textDivs[i].innerText };
      pageText.value.push(item);
    }
  }
  if (props.content) {
    goLocation(props.content);
  }
}
const goLocation = (txt) => {
  //获取页面
  var pageNumber = 0;
  var text =txt;

  var ptText = text.replaceAll('\n', '');
  ptText = ptText.replaceAll(' ', '');
  pageText.value.forEach((item) => {
    item.txt = item.txt.replaceAll('\n', '');
    item.txt = item.txt.replaceAll(' ', '');
    console.log(item.txt);
    if (item.txt.indexOf(ptText.substring(0, 18)) > -1) {
      pageNumber = item.page;
    }
  });
  text = text.replaceAll('\n', '');
  text = text.replaceAll(' ', '');
  if (text.endsWith('。') || text.endsWith('，') || text.endsWith('、')) {
    text = text.substring(0, text.length - 1);
  }
  //'left: 133.17px; top: 152.408px; font-size: 31.3597px; font-family: sans-serif; transform: scaleX(1.01878);'
  var arr = document
    .getElementsByClassName('textLayer')
    [pageNumber - 1].getElementsByTagName('span');
  if (arr) {
    var hightList = [];
    var startIndex = 0;
    var endIndex = 0;
    startIndex = getStartIndex(arr, text, text.length);
    endIndex = getEndIndex(arr, text, text.length, startIndex);
    var currentPageIndex = 0;
    var nextArr = [];
    if (endIndex == undefined) {
      currentPageIndex = arr.length;
      nextArr = document
        .getElementsByClassName('textLayer')
        [pageNumber].getElementsByTagName('span');
      endIndex = getEndIndex(nextArr, text, text.length, startIndex);
    } else {
      currentPageIndex = endIndex;
    }
    for (var i = startIndex; i < currentPageIndex; i++) {
      var element = arr[i];
      var hItem = {};
      var cssText = element.style.cssText;
      var spanText = element.innerText;
      console.log(spanText);
      if (text.includes(spanText)) {
        var topLabel = cssText.split('top: ')[1].split(';')[0];
        topLabel = topLabel.substring(0, topLabel.length - 2);
        var currentItems = [];
        pageContent.value.forEach((item) => {
          if (item.page == pageNumber) {
            currentItems = item.items;
          }
        });
        for (var m = 0; m < currentItems.length; m++) {
          var citem = currentItems[m];
          if (citem.str == spanText) {
            hItem.width = parseFloat(citem.width);
            hItem.height = parseFloat(citem.height);
            hItem.text = spanText;
            hItem.left = parseFloat(cssText.substring(6, cssText.indexOf('px')));
            hItem.top = parseFloat(topLabel);
            hightList.push(hItem);
            if (text.endsWith(citem.str)) {
              break;
            }
          }
        }
      }
    }
    var nextHightList = [];
    //跨页 目前只考虑跨1页
    if (endIndex != undefined) {
      for (var i = 0; i < nextArr.length; i++) {
        var element = nextArr[i];
        var hItem = {};
        var cssText = element.style.cssText;
        var spanText = element.innerText;
        console.log(spanText);
        if (text.includes(spanText)) {
          var topLabel = cssText.split('top: ')[1].split(';')[0];
          topLabel = topLabel.substring(0, topLabel.length - 2);
          var currentItems = [];
          pageContent.value.forEach((item) => {
            if (item.page == pageNumber + 1) {
              currentItems = item.items;
            }
          });
          for (var l = 0; l < currentItems.length; l++) {
            var citem = currentItems[l];
            if (citem.str == spanText) {
              hItem.width = parseFloat(citem.width);
              hItem.height = parseFloat(citem.height);
              hItem.text = spanText;
              hItem.left = parseFloat(cssText.substring(6, cssText.indexOf('px')));
              hItem.top = parseFloat(topLabel);
              nextHightList.push(hItem);
              if (text.endsWith(citem.str)) {
                break;
              }
            }
          }
        }
        if (text.endsWith(spanText)) {
          break;
        }
      }
    }
    //定位
    pdfRef.value.scrollTop = height.value * (pageNumber - 1) + hightList[0]['top'];
    //渲染
    var canvas = document.getElementsByClassName(`page`)[pageNumber - 1];
    const hightDiv = document.createElement('div');
    hightDiv.className = 'highlight-layer flash';
    hightList.forEach((it) => {
      const hDiv = document.createElement('div');
      hDiv.className = 'highlight';
      // 设置内联样式
      hDiv.style.width = it.width * 1.5 + 'px';
      hDiv.style.height = it.height * 1.5 + 'px';
      hDiv.style.left = it.left + 'px';
      hDiv.style.top = it.top + 'px';
      hightDiv.appendChild(hDiv);
    });
    canvas.appendChild(hightDiv);
    if (nextHightList && nextHightList.length > 0) {
      //渲染
      var nextCanvas = document.getElementsByClassName(`page`)[pageNumber];
      const hightDiv = document.createElement('div');
      hightDiv.className = 'highlight-layer flash';
      nextHightList.forEach((it) => {
        const hDiv = document.createElement('div');
        hDiv.className = 'highlight';
        // 设置内联样式
        hDiv.style.width = it.width * 1.5 + 'px';
        hDiv.style.height = it.height * 1.5 + 'px';
        hDiv.style.left = it.left + 'px';
        hDiv.style.top = it.top + 'px';
        hightDiv.appendChild(hDiv);
      });
      nextCanvas.appendChild(hightDiv);
    }
  }
};
const getStartIndex = (arr, text, total) => {
  var count = 0;
  for (var i = 0; i < arr.length; i++) {
    var element = arr[i];
    var spanText = element.innerText;
    console.log('===' + spanText);
    if (text.startsWith(spanText)) {
      return i;
    } else {
      count++;
    }
  }
  if (count == arr.length) {
    start.value = start.value + 1;
    text = text.substring(start.value, total);
    getStartIndex(arr, text, total);
  }
};
const getEndIndex = (arr, text, total, startIndex) => {
  for (var i = 0; i < arr.length; i++) {
    var element = arr[i];
    var spanText = element.innerText;
    console.log('===' + spanText);
    if (text.endsWith(spanText) && spanText.length > 1) {
      return i;
    }
  }
};
const renderPage = (page, PDFJS, num) => {
  return new Promise(async (resolve, reject) => {
    // 先渲染图片
    let pixelRatio = 1;
    const viewport = page.getViewport({ scale: 1.5 });
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.id = `page-${num}`;
    canvas.height = viewport.height * pixelRatio;
    console.log('==height', canvas.height);
    height.value = canvas.height;
    canvas.width = viewport.width * pixelRatio;
    const renderContext = {
      canvasContext: context,
      viewport: viewport,
      transform: [pixelRatio, 0, 0, pixelRatio, 0, 0]
    };
    await page.render(renderContext).promise;
    // 再渲染文字
    const textContent = await page.getTextContent();
    pageContent.value.push({ page: num, items: textContent.items });
    const textLayer = document.createElement('div');
    PDFJS.renderTextLayer({
      textContent: textContent,
      container: textLayer,
      viewport: viewport,
      transform: [pixelRatio, 0, 0, pixelRatio, 0, 0],
      textDivs: []
    });
    textLayer.className = 'textLayer';
    // 将文字覆盖在图片上
    const canvasWrapper = document.createElement('div');
    canvasWrapper.className = 'canvasWrapper';
    const pageDiv = document.createElement('div');
    pageDiv.className = 'page';
    canvasWrapper.appendChild(canvas);
    pageDiv.appendChild(canvasWrapper);
    pageDiv.appendChild(textLayer);
    pdfRef.value.appendChild(pageDiv);
    resolve();
  });
};
</script>
<style scoped lang="scss">
.pdf-container {
  width: 100%;
  height: 100%;
  position: relative;
  .header {
    height: 40px;
    position: sticky;
    display: flex;
    justify-content: center;
    align-items: center;
    border-bottom: 1px solid #eee;
    top: 0px;
    z-index: 9999999;
    background: #fff;
    width: 100%;
    right: 0px;
    left: 0px;
    .title {
      font-size: 18px;
      font-weight: bolder;
      text-overflow: ellipsis;
      width: 0px;
      white-space: nowrap;
      flex-grow: 1;
      overflow: hidden;
      margin-left: 30px;
      margin-right: 40px;
    }
    .close-icon {
      position: absolute;
      top: 10px;
      right: 21px;
      cursor: pointer;
    }
  }
}
.pdf-viewer {
  width: 100%;
  height: calc(100% - 40px);
  position: relative;
  border: 0px solid #ccc;
  overflow-y: auto;
}
</style>
<style>
/* 不能用scoped，因为动态创建的元素不会被编译带上hash */
/* 不加上这些css修饰，元素会错位，样式来自vue-pdf-embed这个库 */
.canvasWrapper {
  position: relative;
  /* display: flex;
  justify-content: center; */
}
.page {
  position: relative;
  box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.08);
  margin: 30px auto;
}
.textLayer {
  text-align: initial;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: hidden;
  opacity: 0.2;
  line-height: 1;
  text-size-adjust: none;
  forced-color-adjust: none;
}
.textLayer span,
.textLayer br {
  color: transparent;
  position: absolute;
  white-space: pre;
  cursor: text;
  transform-origin: 0% 0%;
}
.highlight-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  opacity: 0.15;
  overflow: hidden;
}
.flash {
  animation: flashing 0.6s;
  animation-iteration-count: 2;
}
@keyframes flashing {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 0.15;
  }
}
.highlight {
  background-color: #0076fa;
  position: absolute;
}
</style>