<template>
  <div id="canvas" ref="canvas" v-loading="loading" :element-loading-text="NSTip"
    element-loading-background="rgba(0, 0, 0, 0.8)" style="width:100%;height:100%;position:relative;"
    class="cornerstone-element" @contextmenu.prevent="onContextmenu" @mouseup="sliderMouseup">
    <div v-show="dicomInfo.series" class="info-series">
      <div>Series #{{ dicomInfo.series }}</div>
      <div>Image #{{ dicomInfo.frame }}</div>
      <div>{{ dicomInfo.modality }}</div>
      <div v-if="isComparison" style="font-size: 30px;color: #428bca;">{{ tip }}</div>
    </div>
    <div v-show="dicomInfo.series" class="info-image">
      <!-- <div>
        P {{ dicomInfo.size }}
        <span v-show="dicomInfo.pixel">{{ dicomInfo.pixel }}mm</span>
      </div>
      <div v-show="dicomInfo.thick">Slice Thickness {{ dicomInfo.thick }}mm</div>
      <div>WW/WC {{ dicomInfo.wwwc }}</div>
      <div>Zoom {{ dicomInfo.zoom }}</div>
      <div v-show="dicomInfo.location">Location {{ dicomInfo.location }}mm</div>-->
      <!-- <div v-show="toolState.clipPlaying">FPS {{ dicomInfo.fps }}</div> -->
      <div v-show="mousePosition.mo">
        Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
          '' }}
      </div>
      <div
        v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
        HU: {{ mousePosition.mo }}</div>
      <div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">SUVbw(g/ml): {{ mousePosition.suv.toFixed(3)
      }}</div>
      <div v-else-if="mousePosition.mo">Density: {{ mousePosition.mo }}</div>
      <div>W*H: {{ dicomInfo.size }}</div>

      <div>Zoom: {{ dicomInfo.zoom }}</div>
    </div>

    <div class="info-subject">
      <div v-if="series.subjectCode && IsReadingTaskViewInOrder !== 0">{{ series.subjectCode }}</div>
      <div v-if="series.visitName && IsReadingTaskViewInOrder !== 0">{{ series.visitName }}</div>
      <div>{{ stack.description }}</div>
      <!-- <div>{{ dicomInfo.hospital }}</div> -->
      <!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
      <!-- <div>{{ dicomInfo.name }}</div> -->
      <!-- <div>{{ dicomInfo.sex }} {{ dicomInfo.age }}</div> -->
      <!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
      <!-- <div>{{ dicomInfo.time }}</div> -->
    </div>
    <div ref="sliderBox" class="my_slider_box"
      style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer"
      @click.stop="goViewer($event)">
      <div :style="{ top: height + '%' }"
        style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
        @mousedown="sliderMousedown($event)" />
    </div>
    <div style="position: absolute;left: 50%;top: 15px;color: #f44336;">{{ markers.top }}</div>
    <div style="position: absolute;top: 50%;right: 15px;color: #f44336;">{{ markers.right }}</div>

    <div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">{{ markers.bottom }}</div>
    <div style="position: absolute;top: 50%;left: 15px;color: #f44336;">{{ markers.left }}</div>

    <div class="info-instance">
      <svg-icon icon-class="IsMasked" style="font-size:20px;" v-show="dicomInfo.IsMasked" />
      <!-- <div v-show="dicomInfo.pixel">
        Pixel: {{ dicomInfo.pixel }}mm
      </div>-->
      <div v-show="dicomInfo.location">Location: {{ dicomInfo.location }}</div>
      <div v-show="dicomInfo.thick">Slice Thickness: {{ dicomInfo.thick }}mm</div>
      <div v-show="dicomInfo.wwwc">WW/WL: {{ dicomInfo.wwwc }}</div>
    </div>
    <!-- <div v-show="stack.firstImageLoading" class="load-indicator">
      Loading Series #{{ stack.seriesNumber }}...
    </div>-->
    <el-dialog v-if="dcmTag.visible" :visible.sync="dcmTag.visible" :close-on-click-modal="false" :title="dcmTag.title"
      width="1000px" custom-class="base-dialog-wrapper" append-to-body>
      <dicom-tags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
    </el-dialog>
  </div>
</template>

<script>
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools'
import metaDataProvider, { registerImageSharedCacheKey, unregisterImageSharedCacheKeys } from '@/utils/metaDataProvider'

const scroll = cornerstoneTools.import('util/scrollToIndex')
import Hammer from 'hammerjs'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/invertOrientationString'

const calculateSUV = cornerstoneTools.import('util/calculateSUV')
// import requestPoolManager from '@/utils/request-pool'
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/Note_RectangleRoiTool'
let isMetaDataProviderAdded = false
cornerstoneTools.external.cornerstone = cornerstone
cornerstoneTools.external.Hammer = Hammer
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
cornerstoneTools.toolStyle.setToolWidth(2)
cornerstoneTools.toolColors.setToolColor('rgb(255, 0, 0)')
cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
// cornerstoneTools.init({ showSVGCursors: true })
cornerstoneTools.init()
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
console.log(cornerstoneTools, 'cornerstoneTools')
import DicomTags from './DicomTags'
export default {
  name: 'DicomCanvas',
  components: { DicomTags },
  computed: {
    NSTip() {
      return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
    },
  },
  props: {
    isComparison: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      loading: false,
      canvas: {},
      height: 0,
      stack: {
        seriesId: '',
        instanceId: '',
        seriesNumber: '',
        imageIds: [],
        currentImageIdIndex: 0,
        firstImageLoading: false,
        // preventCache: true
      },
      dicomInfo: {
        hospital: '',
        pid: '',
        name: '',
        sex: '',
        age: '',
        acc: '',
        modality: '',
        time: '',
        series: '',
        frame: '',
        size: '',
        pixel: 0,
        thick: 0,
        wwwc: '',
        zoom: 0,
        location: '',
        fps: 5,
        IsMasked: false
      },
      toolState: {
        initialized: false,
        activeTool: 'none',
        dicomInfoVisible: false,
        clipPlaying: false,
        viewportInvert: false,
      },
      loadImagePromise: null,
      AnnotationSync: null,
      allROIToolData: {},
      type: '',
      series: '',
      ToolStateManager,
      sliderInfo: {
        oldB: null,
        oldM: null,
        isMove: false,
      },
      mousePosition: { x: '', y: '', mo: '' },
      markers: { top: '', right: '', bottom: '', left: '' },
      orientationMarkers: [],
      originalMarkers: [],
      dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') },
      tip: '',
      IsReadingTaskViewInOrder: 2
    }
  },

  mounted() {
    this.type = this.$router.currentRoute.query.type
      ? this.$router.currentRoute.query.type
      : ''
    if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
      this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
    }
    this.canvas = this.$refs.canvas
    this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
    this.canvas.addEventListener(
      'cornerstoneimagerendered',
      this.onImageRendered
    )
    this.canvas.addEventListener(
      'cornerstonetoolsclipstopped',
      this.onClipStopped
    )
    this.canvas.addEventListener('mouseleave', () => {
      this.mousePosition.mo = ''
    })
    this.canvas.addEventListener('cornerstonetoolsmousemove', this.mouseMove)
    document.addEventListener('mouseup', () => {
      this.sliderMouseup()
    })
    document.addEventListener('mousemove', (e) => {
      this.sliderMousemove(e)
    })
    this.canvas.addEventListener(
      'cornerstonetoolsstackscroll',
      this.stackScrollCallback
    )
  },
  beforeDestroy() {
    unregisterImageSharedCacheKeys(this.stack?.imageIds)
  },

  methods: {
    loadImageStack(dicomSeries, text = '') {
      this.tip = text
      this.$nextTick(() => {
        if (!dicomSeries || !Array.isArray(dicomSeries.imageIds) || dicomSeries.imageIds.length === 0) {
          return
        }
        this.series = dicomSeries
        this.stack.seriesId = dicomSeries.seriesId
        this.stack.seriesNumber = dicomSeries.seriesNumber
        this.stack.imageIds = dicomSeries.imageIds
        this.stack.currentImageIdIndex =
          dicomSeries.imageIdIndex &&
            dicomSeries.imageIdIndex < dicomSeries.imageIds.length
            ? dicomSeries.imageIdIndex
            : 0
        this.stack.firstImageLoading = true
        this.stack.description = dicomSeries.description
        this.toolState.viewportInvert = false
        this.toolState.dicomInfoVisible = false
        // var imageId = this.stack.imageIds[this.stack.currentImageIdIndex]
        // var instanceId = imageId.split('/')[imageId.split('/').length - 1]
        // instanceId = instanceId.split('.')[0]
        // this.stack.instanceId = instanceId
        this.toolState.clipPlaying = false
        const element = this.$refs.canvas
        if (!isMetaDataProviderAdded) {
          // 注册自定义 metaDataProvider：统一 SUV 口径（优先接口，缺失回退 DICOM）
          cornerstone.metaData.addProvider(metaDataProvider, 100000)
          isMetaDataProviderAdded = true
        }
        cornerstone.enable(element)
        cornerstoneTools.stopClip(this.canvas)
        this.toolState.clipPlaying = false
        this.loading = true

        cornerstone
          .loadAndCacheImage(
            this.stack.imageIds[this.stack.currentImageIdIndex]
          )
          .then((image) => {
            this.loading = false
            if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
              this.onFirstImageLoaded(image)
            }
          })
          .catch((error) => {
            this.loading = false
            if (error.error && error.error.message) {
              this.$alert(error.error.message)
            }
          })
      })
    },
    onFirstImageLoaded(image) {
      const element = this.$refs.canvas
      var viewport = cornerstone.getDefaultViewportForImage(this.canvas, image)
      cornerstone.displayImage(this.canvas, image, viewport)

      if (!this.toolState.initialized) {
        this.toolState.initialized = true
        const toolButtons = document.querySelectorAll('[data-tool]')
        // const scope = this
        Array.from(toolButtons).forEach((toolBtn) => {
          // Add the tool
          const toolName = toolBtn.getAttribute('data-tool')
          const apiTool = cornerstoneTools[`${toolName}Tool`]

          if (apiTool) {
            const toolAlreadyAddedToElement =
              cornerstoneTools.getToolForElement(element, apiTool)
            if (!toolAlreadyAddedToElement) {
              if (toolName === 'RectangleRoi') {
                cornerstoneTools.addToolForElement(element, apiTool, {
                  configuration: { showMinMax: true, showStatsText: true },
                })
              } else if (toolName === 'EllipticalRoi') {
                cornerstoneTools.addToolForElement(element, apiTool, {
                  configuration: { showMinMax: true },
                })
              } else {
                cornerstoneTools.addToolForElement(element, apiTool)
              }
            }
          }
          // Setup button listener
          // Prevent right click context menu for our menu buttons
          toolBtn.addEventListener(
            'contextmenu',
            (event) => event.preventDefault(),
            true
          )
          // Prevent middle click opening a new tab on Chrome & FF
          toolBtn.addEventListener(
            'auxclick',
            (event) => {
              if (event.button && event.button === 1) {
                event.preventDefault()
              }
            },
            false
          )
        })
        if (
          !cornerstoneTools.getToolForElement(element, Note_RectangleRoiTool)
        ) {
          cornerstoneTools.addToolForElement(element, Note_RectangleRoiTool, {
            configuration: {
              color: '#f00',
              lineWidth: 2,
              drawHandles: false,
              fillColor: 'rgba(0, 0, 0, 1)',
            },
          })
        }
        if (
          !cornerstoneTools.getToolForElement(
            element,
            cornerstoneTools.WwwcRegionTool
          )
        ) {
          cornerstoneTools.addToolForElement(
            element,
            cornerstoneTools.WwwcRegionTool
          )
        }
        if (
          !cornerstoneTools.getToolForElement(
            element,
            cornerstoneTools.StackScrollMouseWheelTool
          )
        ) {
          cornerstoneTools.addToolForElement(
            element,
            cornerstoneTools.StackScrollMouseWheelTool
          )
        }
        cornerstoneTools.setToolActiveForElement(
          element,
          'StackScrollMouseWheel',
          {}
        )
        if (!cornerstoneTools.getToolForElement(element, ScaleOverlayTool)) {
          cornerstoneTools.addToolForElement(element, ScaleOverlayTool)
        }
        cornerstoneTools.setToolActiveForElement(element, 'ScaleOverlay', {})
      }
      // if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.OrientationMarkersTool)) {
      //   cornerstoneTools.addToolForElement(
      //     element,
      //     cornerstoneTools.OrientationMarkersTool
      //   )
      // }
      // cornerstoneTools.setToolActiveForElement(
      //   element,
      //   'OrientationMarkers',
      //   {}
      // )
      cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'playClip'])
      // cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
      cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
      // cornerstoneTools.stackPrefetch.enable(this.canvas)
      cornerstone.updateImage(element, true)
      // cornerstoneTools.stackPrefetch.setConfiguration({ maxImagesToPrefetch: Infinity,
      // preserveExistingPool: true })
      // cornerstoneTools.stackPrefetch.enable(this.canvas)
      // this.stack.imageIds.forEach((item, index) => {
      //   if (index === 0) {
      //     return
      //   }
      //   cornerstone.loadImage(item)
      // })

      this.stack.firstImageLoading = false
      this.toolState.dicomInfoVisible = true
      // 重绘历史标记
      // if (ToolStateManager.toolState.hasOwnProperty(image.imageId) === true) {
      //   return
      // }
      // this.stack.instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
      // var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
      // instanceId = instanceId.split('.')[0]
      // this.stack.instanceId = instanceId
      this.height = this.getStackHeightPercent()
      this.resetWwwc()
    },
    onNewImage(e) {
      e.detail.enabledElement.options = {}
      registerImageSharedCacheKey(
        e.detail.image?.imageId,
        e.detail.image?.sharedCacheKey
      )
      var data = e.detail.image.data
      this.dicomInfo.hospital = data.string('x00080080')
      // let instanceInfo = this.series.instanceInfoList.find(item => item.ImageId === e.detail.image.imageId)
      let instanceInfo = this.series?.instanceInfoList?.find(item => {
        let s1 = item.ImageId ? item.ImageId.split("?")[0] : ''
        let s2 = e.detail.image.imageId ? e.detail.image.imageId.split("?")[0] : ''
        return s1 === s2
      })
      this.dicomInfo.IsMasked = instanceInfo ? instanceInfo.IsMasked : false
      // this.dicomInfo.pid = data.string('x00100020')
      this.dicomInfo.pid = data.string('x00120040')
      this.dicomInfo.name = data.string('x00100010')
      this.dicomInfo.age = data.string('x00101010')
      this.dicomInfo.sex = data.string('x00100040')
      this.dicomInfo.acc = data.string('x00080050') // 登记号
      this.dicomInfo.modality = (data.string('x00080060') || '').trim()
      this.dicomInfo.time = this.formatDicomDateTime(
        data.string('x00080020'),
        data.string('x00080030')
      )
      this.dicomInfo.series = data.string('x00200011')
      this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${this.stack.imageIds.length
        }`
      this.dicomInfo.size = `${data.uint16('x00280011')}x${data.uint16(
        'x00280010'
      )}`
      var pixel = data.floatString('x00280030')
      if (pixel) {
        this.dicomInfo.pixel = pixel.toFixed(2)
      }
      this.dicomInfo.thick = data.floatString('x00180050') // 切片厚度
      if (this.dicomInfo.thick) {
        this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
      }
      const newImageIdIndex = this.stack.imageIds.findIndex(
        (i) => i === e.detail.image.imageId
      )
      if (newImageIdIndex === -1) return
      this.stack.currentImageIdIndex = newImageIdIndex
      this.stack.imageIdIndex = newImageIdIndex
      this.series.imageIdIndex = newImageIdIndex
      this.height = this.getStackHeightPercent()
    },
    getStackHeightPercent() {
      const imageCount = Array.isArray(this.stack.imageIds) ? this.stack.imageIds.length : 0
      if (imageCount <= 1) {
        return 0
      }
      return (this.stack.currentImageIdIndex * 100) / (imageCount - 1)
    },
    stackScrollCallback(e) {
      const { detail } = e
      if (this.isScrollSync) {
        this.$emit('scrollSync', {
          canvasIndex: this.canvasIndex,
          direction: detail.direction,
        })
      }
      this.stack.currentImageIdIndex = e.detail.newImageIdIndex
      this.height = this.getStackHeightPercent()
      // var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()

      // requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
      //   .then(image => {
      //     this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
      //   })
      //   .catch((error) => {
      //     console.log(error)
      //   })
    },
    formatDicomDateTime(date, time) {
      if (date) {
        date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
      }
      if (time) {
        time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
      }
      return time ? `${date} ${time}` : `${date} 00:00:00`
    },

    onImageRendered(e) {
      // var imageId = e.detail.image.imageId
      // var instanceId = imageId.split('/')[imageId.split('/').length - 1]
      // instanceId = instanceId.split('.')[0]

      // if (this.imageId !== instanceId) {
      //   this.getOrientationMarker(e.detail.element)
      //   this.imageId = instanceId
      // }
      this.getOrientationMarker(e.detail.element)
      // this.stack.instanceId = instanceId
      var viewport = e.detail.viewport
      this.dicomInfo.wwwc = `${Math.round(
        viewport.voi.windowWidth
      )}/${Math.round(viewport.voi.windowCenter)}` // 窗位
      // this.dicomInfo.zoom = viewport.scale.toFixed(2)
      this.dicomInfo.zoom = viewport.scale.toFixed(4)
      var data = e.detail.image.data
      const position = data.string('x00201041')
      this.dicomInfo.location = position
    },
    getOrientationMarker(element) {
      console.log('getOrientationMarker')
      const enabledElement = cornerstone.getEnabledElement(element)
      const imagePlane = cornerstone.metaData.get(
        'imagePlaneModule',
        enabledElement.image.imageId
      )

      if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) {
        return
      }

      const row = getOrientationString(imagePlane.rowCosines)
      const column = getOrientationString(imagePlane.columnCosines)
      const oppositeRow = invertOrientationString(row)
      const oppositeColumn = invertOrientationString(column)
      const markers = {
        top: oppositeColumn,
        bottom: column,
        left: oppositeRow,
        right: row,
      }
      if (!markers) {
        return
      }

      this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
      this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
      this.setMarkers()
    },
    setMarkers() {
      var markers = [...this.orientationMarkers]
      for (const key in this.markers) {
        var v = markers.shift(0)
        this.markers[key] = v
      }
    },
    onImageLoaded(e) {
      // var image = e.detail.image
      // // var seriesIndex = -1
      // var seriesUid = image.data.string('x0020000e')
      // console.log(seriesUid)
    },
    getToolForElement(toolName) {
      var isExist = false
      for (var i = 0; i < cornerstoneTools.store.state.tools.length; i++) {
        if (cornerstoneTools.store.state.tools[i].name === toolName) {
          isExist = true
          break
        }
      }
      return isExist
    },
    mouseMove(e) {
      const { element, image, currentPoints } = e.detail
      const x = Math.round(currentPoints.image.x)
      const y = Math.round(currentPoints.image.y)

      const stats = {}

      if (x >= 0 && y >= 0 && x < image.columns && y < image.rows) {
        stats.x = x
        stats.y = y

        if (image.color) {
          stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
        } else {
          stats.storedPixels = cornerstone.getStoredPixels(element, x, y, 1, 1)
          stats.sp = stats.storedPixels[0]
          stats.mo = stats.sp * image.slope + image.intercept
          stats.suv = calculateSUV(image, stats.sp)
        }
      }

      this.mousePosition.x = currentPoints.image.x + 1
      this.mousePosition.y = currentPoints.image.y + 1
      this.mousePosition.mo = stats.mo
      this.mousePosition.suv = stats.suv
    },
    getRGBPixels(element, x, y, width, height) {
      if (!element) {
        return
      }
      x = Math.round(x)
      y = Math.round(y)
      const enabledElement = cornerstone.getEnabledElement(element)
      const storedPixelData = []
      let index = 0
      const pixelData = enabledElement.image.getPixelData()
      let spIndex, row, column

      if (enabledElement.image.color) {
        for (row = 0; row < height; row++) {
          for (column = 0; column < width; column++) {
            spIndex =
              ((row + y) * enabledElement.image.columns + (column + x)) * 4
            const red = pixelData[spIndex]
            const green = pixelData[spIndex + 1]
            const blue = pixelData[spIndex + 2]
            const alpha = pixelData[spIndex + 3]

            storedPixelData[index++] = red
            storedPixelData[index++] = green
            storedPixelData[index++] = blue
            storedPixelData[index++] = alpha
          }
        }
      }

      return storedPixelData
    },
    sliderMousedown(e) {
      var boxHeight = this.$refs['sliderBox'].clientHeight
      this.sliderInfo.oldB =
        (parseInt(e.srcElement.style.top) * boxHeight) / 100
      this.sliderInfo.oldM = e.clientY
      this.sliderInfo.isMove = true
      e.stopImmediatePropagation()
      e.stopPropagation()
      e.preventDefault()
    },
    sliderMousemove(e) {
      if (!this.sliderInfo.isMove) return
      var PX = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
      var boxHeight = this.$refs['sliderBox'].clientHeight
      if (PX < 0) return
      if (PX > boxHeight) return
      var height = (PX * 100) / boxHeight
      var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
      index =
        index > this.stack.imageIds.length
          ? this.stack.imageIds.length
          : index < 0
            ? 0
            : index
      // if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
      this.height = height
      if (this.stack.currentImageIdIndex !== index) {
        scroll(this.canvas, index)
      }
    },
    sliderMouseup(e) {
      this.sliderInfo.isMove = false
    },
    goViewer(e) {
      // console.log(this.$refs['sliderBox'].clientHeight)
      var height = (e.offsetY * 100) / this.$refs['sliderBox'].clientHeight
      this.height = height
      var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
      scroll(this.canvas, index)
    },
    onClipStopped() {
      this.toolState.clipPlaying = false
    },

    onKeyPress(e) {
      var key = e.detail.keyCode
      var keys = { PageUp: 33, PageDown: 34, End: 35, Home: 36 } // Left: 37, Up: 38, Right: 39, Down: 40
      if (key < keys.PageUp || key > keys.Home) return
      if (key === keys.Home) this.scrollPage(-9999)
      else if (key === keys.PageUp) this.scrollPage(-1)
      else if (key === keys.PageDown) this.scrollPage(1)
      else if (key === keys.End) this.scrollPage(9999)
    },

    resizeCanvas() {
      cornerstone.resize(this.canvas, true)
    },

    activateCanvas() {
      this.canvas.tabIndex = 0
      this.canvas.focus()
    },

    resetViewport() {
      this.toolState.viewportInvert = false
      var image = cornerstone.getImage(this.canvas)
      cornerstone.setViewport(
        this.canvas,
        cornerstone.getDefaultViewportForImage(this.canvas, image)
      )
    },

    toggleDicomInfo() {
      this.toolState.dicomInfoVisible = !this.toolState.dicomInfoVisible
      if (this.toolState.dicomInfoVisible) {
        cornerstoneTools.orientationMarkers.enable(this.canvas)
      } else cornerstoneTools.orientationMarkers.disable(this.canvas)
      cornerstone.updateImage(this.canvas)
    },
    setColormap(colormap) {
      const viewport = cornerstone.getViewport(this.canvas)
      viewport.colormap = colormap
      cornerstone.setViewport(this.canvas, viewport)
      cornerstone.updateImage(this.canvas, true)
      if (!colormap) {
        this.resetRenderCanvase(this.canvas)
      }
    },
    resetRenderCanvase(element) {
      const enabledElement = cornerstone.getEnabledElement(element)

      enabledElement.renderingTools.colormapId = undefined
      enabledElement.renderingTools.colorLut = undefined

      const renderCanvas = enabledElement.renderingTools.renderCanvas
      const canvasContext = renderCanvas.getContext('2d')
      canvasContext.fillStyle = 'white'
      canvasContext.fillRect(0, 0, renderCanvas.width, renderCanvas.height)

      const renderCanvasData = canvasContext.getImageData(
        0,
        0,
        renderCanvas.width,
        renderCanvas.height
      )

      enabledElement.renderingTools.renderCanvasContext = canvasContext
      enabledElement.renderingTools.renderCanvasData = renderCanvasData
    },
    scrollPage(offset) {
      if (this.loading) return
      var index = this.stack.currentImageIdIndex + offset
      if (index < 0) index = 0
      else if (index >= this.stack.imageIds.length) {
        index = this.stack.imageIds.length - 1
      }
      if (index !== this.stack.currentImageIdIndex) {
        scroll(this.canvas, index)
      }
    },

    toggleClipPlay() {
      if (this.loading) return
      if (this.toolState.clipPlaying) {
        cornerstoneTools.stopClip(this.canvas)
        this.toolState.clipPlaying = false
        return
      }
      this.toolState.clipPlaying = true
      cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
      cornerstoneTools.getToolState(this.canvas, 'playClip').data[0].loop = true
    },
    setFps(fps) {
      this.dicomInfo.fps = fps
    },

    resetWwwc() {
      this.toolState.viewportInvert = false
      var viewport = cornerstone.getViewport(this.canvas)
      // viewport.invert = false
      var image = cornerstone.getImage(this.canvas)
      if (!viewport || !image) return
      viewport.voi.windowWidth = image.windowWidth
      viewport.voi.windowCenter = image.windowCenter
      cornerstone.setViewport(this.canvas, viewport)
    },

    setWwwc(ww, wc) {
      var viewport = cornerstone.getViewport(this.canvas)
      viewport.voi.windowWidth = ww
      viewport.voi.windowCenter = wc
      cornerstone.setViewport(this.canvas, viewport)
    },

    toggleInvert() {
      this.toolState.viewportInvert = !this.toolState.viewportInvert
      var viewport = cornerstone.getViewport(this.canvas)
      viewport.invert = this.toolState.viewportInvert
      cornerstone.setViewport(this.canvas, viewport)
    },

    activateZoom() {
      cornerstoneTools.addTool(cornerstoneTools.ZoomTool, {
        configuration: {
          invert: false,
          preventZoomOutsideImage: false,
          minScale: 0.1,
          maxScale: 20.0,
        },
      })
      cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
      this.toolState.activeTool = 'zoom'
    },

    resetRotate() {
      if (this.originalMarkers.length > 0) {
        this.orientationMarkers = [...this.originalMarkers]
        this.setMarkers()
      }

      var viewport = cornerstone.getViewport(this.canvas)
      viewport.hflip = false
      viewport.vflip = false
      viewport.rotation = 0
      cornerstone.setViewport(this.canvas, viewport)
    },

    setRotate(hflip, vflip, angle, type) {
      if (this.orientationMarkers.length > 0) {
        var markers = [...this.orientationMarkers]
        if (type === 2) {
          // 垂直翻转
          this.orientationMarkers[1] = markers[3]

          this.orientationMarkers[3] = markers[1]
        } else if (type === 3) {
          // 水平翻转
          this.orientationMarkers[0] = markers[2]
          this.orientationMarkers[2] = markers[0]
        } else if (type === 4) {
          // 左转90度
          this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
        } else if (type === 5) {
          // 右转90度
          this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
        }
        this.setMarkers()
      }
      var viewport = cornerstone.getViewport(this.canvas)
      if (hflip) viewport.hflip = !viewport.hflip
      if (vflip) viewport.vflip = !viewport.vflip
      if (angle !== 0) viewport.rotation += angle
      cornerstone.setViewport(this.canvas, viewport)
    },

    saveImage() {
      var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
      cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
    },
    showTags() {
      this.dcmTag.visible = true
    },
    fitToWindow() {
      if (this.stack.seriesNumber) {
        cornerstone.fitToWindow(this.canvas)
      }
    },
    fitToImage() {
      if (this.stack.seriesNumber) {
        const enabledElement = cornerstone.getEnabledElement(this.canvas)
        enabledElement.viewport.scale = 1
        cornerstone.updateImage(this.canvas)
      }
    },
    clearMeasurement() {
      const viewport = cornerstone.getViewport(this.canvas)
      if (viewport.colormap) {
        this.resetRenderCanvase(this.canvas)
      }
      ToolStateManager.clear(this.canvas)
      cornerstone.setViewport(
        this.canvas,
        cornerstone.getDefaultViewportForImage(
          this.canvas,
          cornerstone.getImage(this.canvas)
        )
      )
      cornerstone.updateImage(this.canvas)
    },
    setToolPassive(toolName) {
      cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
    },
    async reloadImage(newImageId = null) {
      // 1. 获取当前imageId（如果未指定新imageId）
      let element = this.canvas
      this.stack.imageIds.splice(this.stack.currentImageIdIndex, 1, newImageId)
      const currentImageId =
        newImageId || cornerstone.getImage(element)?.imageId

      if (!currentImageId) {
        console.error('没有找到可用的imageId')
        return
      }

      // 2. 清除该影像关联的工具状态（标注数据）
      this.clearToolStateForImage(element, currentImageId)

      // 3. 从缓存中移除该影像
      this.removeImageFromCache(currentImageId)

      // 4. 重新加载并渲染
      await this.loadAndRenderImage(element, currentImageId)
    },
    clearToolStateForImage(element, imageId) {
      // 获取全局状态管理器
      const globalToolStateManager =
        cornerstoneTools.globalImageIdSpecificToolStateManager

      if (globalToolStateManager) {
        // 方式1：清空该影像的全部工具数据
        globalToolStateManager.clearImageIdToolState(imageId)
        console.log(`已清除影像 ${imageId} 的所有标注数据`)
      }

      // 方式2：如果使用元素级别的状态管理器
      const elementToolStateManager =
        cornerstoneTools.getElementToolStateManager(element)
      if (elementToolStateManager && elementToolStateManager.get(element)) {
        // 清空该元素上当前显示影像的数据
        elementToolStateManager.clear(element)
      }
    },
    removeImageFromCache(imageId) {
      const imageCache = cornerstone.imageCache

      if (imageCache && imageCache[imageId]) {
        // 从缓存中移除
        delete imageCache[imageId]
        console.log(`已从缓存中移除影像: ${imageId}`)
      }

      // 也可以使用官方API（如果可用）
      if (typeof cornerstone.imageCache.removeImage === 'function') {
        cornerstone.imageCache.removeImageLoadObject(imageId)
      }
    },
    async loadAndRenderImage(element, imageId) {
      try {
        // 1. 清除当前画布内容（可选）
        const canvas = element.querySelector('canvas')
        if (canvas) {
          const ctx = canvas.getContext('2d')
          ctx.clearRect(0, 0, canvas.width, canvas.height)
        }

        // 2. 重新加载图像（强制从源头重新获取）
        const image = await cornerstone.loadAndCacheImage(imageId)

        // 3. 获取或创建视口设置
        let viewport = cornerstone.getViewport(element)
        if (!viewport) {
          viewport = cornerstone.getDefaultViewport(element, image)
        }

        // 4. 显示图像
        cornerstone.displayImage(element, image, viewport)

        // 5. 触发重绘
        cornerstone.updateImage(element)

        console.log(`影像 ${imageId} 重新加载并渲染完成`)

        return image
      } catch (error) {
        console.error('加载图像失败:', error)
        throw error
      }
    },
    getNote_RectangleRoi() {
      return new Promise(resolve => {
        let toolInfo = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
        let image = cornerstone.getImage(this.canvas)
        resolve({ toolInfo, image })
      })
      // console.log(
      //   cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
      // )
      // console.log(cornerstone.getImage(this.canvas))
      // let image = cornerstone.getImage(this.canvas)
      // // cornerstone.imageCache.removeImageLoadObject(image.imageId)

      // this.reloadImage(this.canvas, image.imageId)
    },
    removeNote_RectangleRoi() {
      const toolState = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi');
      if (toolState && toolState.data.length > 0) {
        let arr = toolState.data.map(item => item)
        arr.forEach(item => {
          cornerstoneTools.removeToolState(this.canvas, 'Note_RectangleRoi', item);
        })
        cornerstone.updateImage(this.canvas);
      }
    },
    setToolActive(toolName) {
      cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
        mouseButtonMask: 1,
      })
    },
    setAllToolsPassive() {
      cornerstoneTools.store.state.tools.forEach((tool) => {
        cornerstoneTools.setToolPassiveForElement(this.canvas, tool.name)
      })
    },

    addTargetElement(synchronizer) {
      synchronizer.addTarget(this.$refs.canvas)
    },
    removeTarget(synchronizer) {
      synchronizer.removeTarget(this.$refs.canvas)
    },
    addSourceElement(synchronizer) {
      synchronizer.addSource(this.$refs.canvas)
    },
    removeSource(synchronizer) {
      synchronizer.removeSource(this.$refs.canvas)
    },
    activeReferenceLine(synchronizer) {
      if (
        !cornerstoneTools.getToolForElement(
          this.canvas,
          cornerstoneTools.ReferenceLinesTool
        )
      ) {
        cornerstoneTools.addToolForElement(
          this.canvas,
          cornerstoneTools.ReferenceLinesTool
        )
      }
      cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
        synchronizationContext: synchronizer,
      })

      // cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
      // cornerstoneTools.setToolActive('Crosshairs', {
      //   mouseButtonMask: 1,
      //   synchronizationContext: synchronizer
      // })
    },
    disabledReferenceLine(synchronizer) {
      synchronizer.enabled = false
      synchronizer.remove(this.canvas)
      cornerstoneTools.setToolDisabledForElement(this.canvas, 'ReferenceLines')
      // cornerstoneTools.setToolDisabledForElement(this.canvas, 'Crosshairs')
    },
    activeViewPortToolSync(synchronizer, toolName) {
      synchronizer.add(this.canvas)
      synchronizer.enabled = true
      if (
        !cornerstoneTools.getToolForElement(
          this.canvas,
          cornerstoneTools[`${toolName}Tool`]
        )
      ) {
        cornerstoneTools.addToolForElement(
          this.canvas,
          cornerstoneTools[`${toolName}Tool`]
        )
      }
      cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
        mouseButtonMask: 1,
        synchronizationContext: synchronizer,
      })
    },
    disabledViewPortToolSync(synchronizer, toolName) {
      synchronizer.enabled = false
      synchronizer.remove(this.canvas)
      cornerstoneTools.setToolDisabledForElement(this.canvas, toolName)
    },
    activeImageSync(synchronizer) {
      synchronizer.add(this.$refs.canvas)
      synchronizer.enabled = true
      return false
    },
    disabledImageSync(synchronizer) {
      synchronizer.remove(this.$refs.canvas)
      synchronizer.enabled = false
      return false
    },
    activeAnnotationSync(synchronizer) {
      this.AnnotationSync = synchronizer
      synchronizer.add(this.$refs.canvas)
      synchronizer.enabled = true
    },
    disabledAnnotationSync(synchronizer) {
      this.AnnotationSync = null
      synchronizer.enabled = false
      synchronizer.remove(this.$refs.canvas)
      this.setAllToolsPassive()
    },
    onContextmenu(e) {
      e.stopImmediatePropagation()
      e.stopPropagation()
      e.preventDefault()
      // const colormapsList = cornerstone.colors.getColormapsList()
      // const colorItems = []
      // colorItems.push({
      //   label: '默认值',
      //   onClick: () => {
      //     this.setColormap()
      //   }
      // })
      // colormapsList.forEach(colormap => {
      //   const item = {}
      //   item.label = colormap.name
      //   item.onClick = () => {
      //     this.setColormap(colormap.id)
      //   }
      //   colorItems.push(item)
      // })
      // this.$contextmenu({
      //   items: [
      //     {
      //       label: '移动',
      //       divided: true,
      //       onClick: () => {
      //         this.setToolActive('Pan')
      //       }
      //     },
      //     {
      //       label: '缩放',
      //       divided: true,
      //       children: [
      //         {
      //           label: '自由缩放',
      //           onClick: () => {
      //             this.setToolActive('Zoom')
      //           }
      //         },
      //         {
      //           label: '适应图像',
      //           onClick: () => {
      //             this.fitToWindow()
      //           }
      //         },
      //         {
      //           label: '适应窗口',
      //           onClick: () => {
      //             this.fitToImage()
      //           }
      //         }
      //       ]
      //     },
      //     {
      //       label: '透镜',
      //       divided: true,
      //       onClick: () => {
      //         this.setToolActive('Magnify')
      //       }
      //     },
      //     {
      //       label: '旋转',
      //       divided: true,
      //       children: [
      //         {
      //           label: '默认值',
      //           onClick: () => {
      //             this.resetRotate()
      //           }
      //         },
      //         {
      //           label: '自由旋转',
      //           onClick: () => {
      //             this.setToolActive('Rotate')
      //           }
      //         },
      //         {
      //           label: '水平翻转',
      //           onClick: () => {
      //             this.setRotate(true, false, 0)
      //           }
      //         },
      //         {
      //           label: '垂直翻转',
      //           onClick: () => {
      //             this.setRotate(false, true, 0)
      //           }
      //         },
      //         {
      //           label: '左转90度',
      //           onClick: () => {
      //             this.setRotate(false, false, -90)
      //           }
      //         },
      //         {
      //           label: '右转90度',
      //           onClick: () => {
      //             this.setRotate(false, false, 90)
      //           }
      //         }
      //       ]
      //     },

      //     {
      //       label: '测量',
      //       divided: true,
      //       minWidth: 0,
      //       children: [
      //         {
      //           label: '探针',
      //           onClick: () => {
      //             this.setToolActive('Probe')
      //           }
      //         },
      //         {
      //           label: '长度测量',
      //           onClick: () => {
      //             this.setToolActive('Length')
      //           }
      //         },
      //         {
      //           label: '角度测量',
      //           onClick: () => {
      //             this.setToolActive('Angle')
      //           }
      //         },
      //         {
      //           label: 'Cobb测量',
      //           onClick: () => {
      //             this.setToolActive('CobbAngle')
      //           }
      //         },
      //         {
      //           label: '椭圆测量',
      //           onClick: () => {
      //             this.setToolActive('EllipticalRoi')
      //           }
      //         },
      //         {
      //           label: '矩形测量',
      //           onClick: () => {
      //             this.setToolActive('RectangleRoi')
      //           }
      //         },
      //         {
      //           label: '多边形标记',
      //           onClick: () => {
      //             this.setToolActive('FreehandRoi')
      //           }
      //         },
      //         {
      //           label: '十字线',
      //           onClick: () => {
      //             this.setToolActive('Bidirectional')
      //           }
      //         },
      //         {
      //           label: '文字标注',
      //           onClick: () => {
      //             this.setToolActive('ArrowAnnotate')
      //           }
      //         }
      //       ]
      //     },
      //     {
      //       label: '调窗',
      //       divided: true,
      //       onClick: () => {
      //         this.setToolActive('Wwwc')
      //       }
      //     },
      //     {
      //       label: '反色',
      //       divided: true,
      //       onClick: () => {
      //         this.toggleInvert()
      //       }
      //     },
      //     {
      //       label: '伪彩',
      //       children: colorItems
      //     }
      //   ],
      //   event,
      //   // x: event.clientX,
      //   // y: event.clientY,
      //   customClass: 'class-a',
      //   zIndex: 3,
      //   minWidth: 100
      // })
      // return false
    },
    getToolSate() {
      const toolROITypes = [
        'Probe',
        'EllipticalRoi',
        'RectangleRoi',
        'ArrowAnnotate',
        'Length',
        'CobbAngle',
        'Angle',
        'Bidirectional',
        'FreehandRoi',
      ]
      for (let i = 0; i < toolROITypes.length; i++) {
        const toolROIType = toolROITypes[i]
        const toolROIData = JSON.stringify(
          cornerstoneTools.getToolState(this.canvas, toolROIType)
        )

        if (toolROIData !== undefined) {
          this.allROIToolData[toolROITypes[i]] = JSON.parse(toolROIData)
        }
      }
    },
    clearToolState() {
      ToolStateManager.clear(this.canvas)
      cornerstone.updateImage(this.canvas)
    },
    removeLabel(item) {
      const promise = scroll(this.canvas, item.data.imageIdIndex)
      const scope = this
      Promise.all([promise]).then((res) => {
        cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
        cornerstone.updateImage(scope.canvas)
      })
    },
  },
}
</script>

<style scoped>
.info-series {
  position: absolute;
  left: 10px;
  top: 10px;
  text-align: left;
  color: #ddd;
  font-size: 12px;
  /* z-index: 1; */
}

.info-image {
  position: absolute;
  left: 10px;
  bottom: 10px;
  text-align: left;
  color: #ddd;
  font-size: 12px;
  /* z-index: 1; */
}

.info-subject {
  position: absolute;
  right: 15px;
  top: 10px;
  text-align: right;
  color: #ddd;
  font-size: 12px;
  /* z-index: 1; */
}

.info-instance {
  position: absolute;
  right: 15px;
  bottom: 10px;
  text-align: right;
  color: #ddd;
  font-size: 12px;
  /* z-index: 1; */
}

.load-indicator {
  position: absolute;
  left: 10px;
  top: 10px;
  text-align: left;
  /* z-index: 1; */
}

.magnifyTool {
  border: 2px solid #ffffff;
  border-radius: 50%;
  display: none;
  cursor: none;
}

.menu__item {
  display: block;
  line-height: 20px;
  text-align: center;
  margin: 10px;
  cursor: default;
}

.menu__item:hover {
  color: #ff0000;
}

.menu {
  height: auto;
  width: auto;
  position: absolute;
  font-size: 14px;
  text-align: left;
  border-radius: 10px;
  border: 1px solid #c21111;
  background-color: #ffffff;
}

li:hover {
  background-color: #e0e0e2;
  color: white;
}

.my_slider_box:after {
  content: '';
  position: absolute;
  bottom: -20px;
  left: 0;
  height: 20px;
  width: 100%;
  background: #333;
}
</style>
