<template>
    <div ref="viewport-volume" class="viewport-wrapper" v-loading="loading" :element-loading-text="NSTip"
        element-loading-background="rgba(0, 0, 0, 0.8)" @mouseup="sliderMouseup" @mousemove="sliderMousemove"
        @mouseleave="sliderMouseleave" :style="{ color: '#ddd' }">
        <div v-if="series && taskInfo" class="left-top-text">
            <div v-if="taskInfo.IsExistsClinicalData" class="cd-info" :title="$t('trials:reading:button:clinicalData')">
                <svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon"
                    @click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
            </div>
            <h2 v-if="taskInfo.IsReadingShowSubjectInfo && series.TaskInfo" class="subject-info">
                {{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
            </h2>
            <div>Series: #{{ series.SeriesNumber }}</div>
            <div v-if="imageInfo.total">Image: #{{ `${series.SliceIndex + 1}/${imageInfo.total}` }}</div>
            <div>{{ series.Modality }}</div>
        </div>
        <div v-if="series" class="right-top-text">
            <div>{{ series.Description }}</div>
            <div class="colorBar" :style="`background-color:${getColor()}`"></div>
        </div>
        <div v-if="series" class="left-bottom-text">
            <div v-show="mousePosition.index.length > 0">
                Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
            </div>
            <div
                v-if="(series.Modality === 'CT' || series.Modality === 'DR' || series.Modality === 'CR') && mousePosition.value">
                HU: {{ mousePosition.value }}
            </div>
            <div v-else-if="(series.Modality === 'PT' && mousePosition.value)">
                SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.value.toFixed(3) :
                    mousePosition.value.toFixed(digitPlaces)
                }}
            </div>
            <div v-else-if="mousePosition.value">
                Density: {{ mousePosition.value }}
            </div>
            <div v-show="imageInfo.size">
                W*H: {{ imageInfo.size }}
            </div>
        </div>
        <div v-if="series" class="right-bottom-text">
            <div v-show="imageInfo.location">Location: {{
                `${Number(imageInfo.location).toFixed(digitPlaces)} mm`
                }}</div>
            <div v-show="imageInfo.sliceThickness">Slice Thickness: {{
                `${Number(imageInfo.sliceThickness).toFixed(digitPlaces)} mm`
                }}</div>
            <div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
        </div>
        <div class="orientation-top">
            {{ markers.top }}
        </div>
        <div class="orientation-right">
            {{ markers.right }}
        </div>

        <div class="orientation-bottom">
            {{ markers.bottom }}
        </div>
        <div class="orientation-left">
            {{ markers.left }}
        </div>
        <div ref="sliderBox" class="right-slider-box" @click.stop="clickSlider($event)">
            <div :style="{ top: sliderInfo.height + '%' }" class="slider" @click.stop.prevent="() => { return }"
                @mousedown.stop="sliderMousedown($event)" />
        </div>
    </div>
</template>
<script>
import {
    metaData,
    getRenderingEngine,
    utilities as csUtils,
    cache
} from '@cornerstonejs/core'
import * as cornerstoneTools from '@cornerstonejs/tools'
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
import { setCtMappingRange } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
import {
    setPetTransferFunctionForVolumeActor
} from './helpers/index.js'
import { vec3, mat4 } from 'gl-matrix'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
import {
    renderSegmentation,
    readingSegmentByConfig,
    selectSegmentation,
    selectSegment,
    createSegmentationRepresentation,
    viewSegmentation,
    viewSegment,
    jumpBidirectional,
    viewBidirectional,
    changeColor,
    resetViewport
} from "./helpers/segmentations"
export default {
    name: 'MPRViewport',
    props: {
        renderingEngineId: {
            type: String,
            required: true
        },
        viewportId: {
            type: String,
            required: true
        },
        viewportIndex: {
            type: Number,
            required: true
        },
        MPRInfo: {
            type: Object,
            default: () => {
                return {}
            }
        },
        histogramVisible: {
            type: Boolean,
            default: false
        },
        actionConfiguration: {
            type: Object,
            default: () => {
                return {}
            }
        },
        SegmentConfig: {
            type: Object,
            default: () => {
                return {}
            }
        },
        curSegSeries: {
            type: Object,
            default: () => {
                return {}
            }
        },
        segmentIndex: {
            type: Number,
            default: 0
        },
        segmentationId: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            element: '',
            series: {},
            ctSeries: {},
            petSeries: {},
            taskInfo: null,
            sliderInfo: {
                oldB: null,
                oldM: null,
                isMove: false,
                height: 0
            },
            mousePosition: {
                index: [],
                value: null,
                modalityUnit: '',
                world: []
            },
            imageInfo: {
                zoom: null,
                size: null,
                location: null,
                sliceThickness: null,
                wwwc: null,
                total: 0,
            },
            digitPlaces: 2,
            orientationMarkers: [],
            originalMarkers: [],
            markers: { top: '', right: '', bottom: '', left: '' },
            playClipState: false,
            wwwcIdx: 2,
            presetName: '',
            volumeId: null,
            defaultWindowLevel: {},
            rotateAngle: 0,
            rotateBarLeft: 0,
            loading: false,
            toggleClipPlayTimer: null,
            isFlip: false
        }
    },
    mounted() {
        this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
        const digitPlaces = Number(localStorage.getItem('digitPlaces'))
        this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
        this.$nextTick(() => {
            this.initViewport()
        })
        DicomEvent.$on('createSegmentationRepresentation', (segmentationId) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            createSegmentationRepresentation(this.viewportId, segmentationId)
        })
        DicomEvent.$on('viewSegmentation', (obj) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            viewSegmentation(obj, this.viewportId)
        })
        DicomEvent.$on('viewSegment', (obj) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            viewSegment(obj, this.viewportId)
        })
        DicomEvent.$on('jumpBidirectional', (obj) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            jumpBidirectional(obj, this.viewportId, this.volumeId)
        })
        DicomEvent.$on('viewBidirectional', (obj) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            viewBidirectional(obj, this.viewportId)
        })
        DicomEvent.$on('changeColor', (obj) => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            changeColor(obj, this.viewportId)
        })
        DicomEvent.$on('resetViewport', () => {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
            resetViewport(this.viewportId)
        })
        DicomEvent.$on('renderSegmentation', async (viewportId) => {
            // if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
            if (this.viewportId !== viewportId) return false
            await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration, this.segmentationId, this.segmentIndex)
        })
    },
    watch: {
        MPRInfo: {
            handler() {
                if (!this.series.orientation) return false
                switch (this.series.orientation) {
                    case 'AXIAL':
                        this.imageInfo.size = `${this.MPRInfo.SAGITTAL.imageNum}*${this.MPRInfo.CORONAL.imageNum}`
                        break;
                    case 'CORONAL':
                        this.imageInfo.size = `${this.MPRInfo.SAGITTAL.imageNum}*${this.MPRInfo.AXIAL.imageNum}`
                        break;
                    case 'SAGITTAL':
                        this.imageInfo.size = `${this.MPRInfo.CORONAL.imageNum}*${this.MPRInfo.AXIAL.imageNum}`
                        break;
                }
            },
            deep: true
        },
        SegmentConfig: {
            handler() {
                if (!this.segmentationId) return false
                if (!this.series.TaskInfo) return false
                readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
            },
            deep: true
        },
        segmentIndex() {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
            if (this.segmentIndex <= 0) return false
            selectSegment(this.viewportId, this.segmentationId, this.segmentIndex)
        },
        segmentationId() {
            if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
            if (!this.segmentationId) return false
            selectSegmentation(this.viewportId, this.segmentationId)
            readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
        }
    },
    methods: {
        getColor() {
            let color = '#000'
            switch (this.series.orientation) {
                case 'AXIAL':
                    color = '#00f'
                    break;
                case 'CORONAL':
                    color = '#f00'
                    break;
                case 'SAGITTAL':
                    color = '#0f0'
                    break;
            }
            return color
        },
        initViewport() {
            this.element = this.$refs['viewport-volume']
            const resizeObserver = new ResizeObserver(() => {
                const renderingEngine = getRenderingEngine(this.renderingEngineId)
                if (renderingEngine) {
                    renderingEngine.resize(true, false)
                }
            })
            this.element.oncontextmenu = (e) => e.preventDefault()
            // resizeObserver.observe(this.element)
            this.element.addEventListener("CORNERSTONE_VOLUME_NEW_IMAGE", this.stackNewImage)
            this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
            this.element.addEventListener('wheel', (e) => {
                // if (this.histogramVisible) return false
                // console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
                const renderingEngine = getRenderingEngine(this.renderingEngineId)
                const viewport = renderingEngine.getViewport(this.viewportId)
                const currentImageIdIndex = viewport.getCurrentImageIdIndex()
                const totalImages = this.imageInfo.total;

                // 手动实现循环逻辑
                if (currentImageIdIndex >= totalImages - 1 && e.wheelDeltaY < 0) {
                    // 滚动到最后一张时跳回第一张
                    csUtils.jumpToSlice(viewport.element, { imageIndex: 0 });
                } else if (currentImageIdIndex <= 0 && e.wheelDeltaY > 0) {
                    // 滚动到第一张时跳回最后一张
                    csUtils.jumpToSlice(viewport.element, { imageIndex: totalImages - 1 });
                }
            });
            this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
            // this.element.addEventListener(cornerstoneTools.Enums.Events.MOUSE_WHEEL, this.handletoolsMouseWheel)
            this.element.addEventListener('mouseleave', () => {
                this.mousePosition.index = []
                this.mousePosition.value = null
            })
            document.addEventListener('mouseup', () => {
                this.sliderMouseup()
            })
            document.addEventListener('mousemove', (e) => {
                this.sliderMousemove(e)

            })
        },

        determineImagePlane(imageOrientationPatient) {
            // imageOrientationPatient 是 [rowX, rowY, rowZ, colX, colY, colZ]
            // 我们只关心行方向向量 (rowX, rowY, rowZ)
            const [rowX, rowY, rowZ] = imageOrientationPatient;

            // 计算行方向向量与 X, Y, Z 轴的点积（因为轴向量是单位向量，所以点积就是投影长度）
            const dotX = Math.abs(rowX);
            const dotY = Math.abs(rowY);
            const dotZ = Math.abs(rowZ);

            // 找到最大的点积，确定主方向
            const maxDot = Math.max(dotX, dotY, dotZ);

            // 根据主方向判断解剖面
            if (maxDot === dotX) {
                // 行方向接近 X 轴，说明视线方向接近 Y 或 Z 轴。
                // 更准确的判断是看视线方向（由行和列向量叉乘得到）。
                // 但一个简化的、在大多数情况下都成立的规则是：
                // 如果行向量主要在 X-Y 平面 (rowZ 很小)，则为 Axial。
                // 如果行向量主要在 X-Z 平面 (rowY 很小)，则为 Sagittal。
                // 为了简化，我们可以直接根据视线方向（法线）来判断。
                // 法线方向 = 行向量 × 列向量
                const [colX, colY, colZ] = imageOrientationPatient.slice(3);
                const normalX = rowY * colZ - rowZ * colY;
                const normalY = rowZ * colX - rowX * colZ;
                const normalZ = rowX * colY - rowY * colX;

                const absNormalX = Math.abs(normalX);
                const absNormalY = Math.abs(normalY);
                const absNormalZ = Math.abs(normalZ);

                const maxNormal = Math.max(absNormalX, absNormalY, absNormalZ);

                if (maxNormal === absNormalZ) {
                    return 'AXIAL';
                } else if (maxNormal === absNormalY) {
                    return 'SAGITTAL';
                } else if (maxNormal === absNormalX) {
                    return 'CORONAL';
                }

            } else if (maxDot === dotY) {
                // 行方向接近 Y 轴，通常是 Coronal 面。
                return 'SAGITTAL';
            } else if (maxDot === dotZ) {
                // 行方向接近 Z 轴，通常是 Sagittal 面。
                return 'CORONAL';
            }

            return 'unknown';
        },
        setFilp(f = false) {
            this.isFlip = f
        },
        stackNewImage(e) {
            if (this.isFlip) return this.isFlip = false
            const { detail } = e
            this.series.SliceIndex = detail.imageIndex
            this.sliderInfo.height = detail.imageIndex * 100 / detail.numberOfSlices
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            const zoom = viewport.getZoom()
            this.imageInfo.zoom = zoom.toFixed(4)
            let imageIds = viewport.getImageIds(this.volumeId)
            let imageId = imageIds[0]
            let volume = cache.getVolume(this.volumeId)
            let spacing = volume ? volume.spacing : []
            // if (this.series.orientation === 'AXIAL') imageId = viewport.getCurrentImageId() 
            if (imageId && volume) {
                this.$emit('setMPRInfo', { type: this.series.orientation, key: "imageNum", value: detail.numberOfSlices })
                const imagePlaneModule = metaData.get('imagePlaneModule', imageId)
                let type = this.determineImagePlane(imagePlaneModule.imageOrientationPatient)
                this.imageInfo.location = type === this.series.orientation ? imagePlaneModule.sliceLocation : ''
                this.imageInfo.sliceThickness = type === this.series.orientation ? spacing[2] : spacing[0]
                this.imageInfo.total = detail.numberOfSlices
                this.getOrientationMarker()
                this.$emit("resetHistogram")
                let properties = viewport.getProperties(this.volumeId)
                if (properties && properties.voiRange) {
                    var { lower, upper } = properties.voiRange
                    const windowWidth = upper - lower
                    const windowCenter = (upper + lower) / 2
                    this.defaultWindowLevel.windowWidth = windowWidth
                    this.defaultWindowLevel.windowCenter = windowCenter
                    this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
                }
            }
            if (volume) {
                const toolGroupId = 'share-viewport-volume'
                const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
                toolGroup.setToolEnabled('ScaleOverlay')
            }
            // const toolGroupId = this.viewportId
        },
        setFullScreen(index) {
            this.series.SliceIndex = index
            setTimeout(() => {
                const renderingEngine = getRenderingEngine(this.renderingEngineId)
                const viewport = renderingEngine.getViewport(
                    this.viewportId
                )
                csUtils.jumpToSlice(viewport.element, { imageIndex: index })
                viewport.render()
            })
        },
        voiModified(e) {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            let properties = viewport.getProperties()
            if (properties && properties.voiRange) {
                var { lower, upper } = properties.voiRange
                const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
                    lower,
                    upper
                )
                this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
                this.$emit('upperRangeChange', Math.round(windowWidth))
            }
        },
        getOrientationMarker() {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            const { viewUp, viewPlaneNormal } = viewport.getCamera()

            const viewRight = vec3.create()
            vec3.cross(viewRight, viewUp, viewPlaneNormal)

            const columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]]
            const rowCosines = viewRight
            const rowString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(rowCosines)
            const columnString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(columnCosines)
            const oppositeRowString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(rowString)
            const oppositeColumnString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(columnString)
            this.markers.top = oppositeColumnString
            this.markers.right = rowString
            this.markers.bottom = columnString
            this.markers.left = oppositeRowString
            this.orientationMarkers = [oppositeColumnString, rowString, columnString, oppositeRowString]
            if (this.originalMarkers.length === 0) {
                this.originalMarkers = [...this.orientationMarkers]
            }
        },
        setMarkers() {
            const markers = [...this.orientationMarkers]
            for (const key in this.markers) {
                const v = markers.shift(0)
                this.markers[key] = v
            }
        },
        resetOrientationMarkers() {
            if (this.originalMarkers.length > 0) {
                this.orientationMarkers = [...this.originalMarkers]
                this.setMarkers()
            }
        },
        rotateOrientationMarkers(type) {
            if (this.orientationMarkers.length > 0) {
                if (type === 1) {
                    this.resetOrientationMarkers()
                    return
                }
                const markers = [...this.orientationMarkers]
                if (type === 2) {
                    // 垂直翻转
                    this.orientationMarkers[0] = markers[2]
                    this.orientationMarkers[2] = markers[0]
                } else if (type === 3) {
                    // 水平翻转
                    this.orientationMarkers[1] = markers[3]
                    this.orientationMarkers[3] = markers[1]
                } 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()
            }
        },
        toggleClipPlay(isPlay, framesPerSecond) {
            this.playClipState = isPlay
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            if (isPlay) {
                this.toggleClipPlayTimer = setInterval(() => {
                    let index = this.series.SliceIndex + 1;
                    if (index > this.imageInfo.total - 1) index = 0
                    csUtils.jumpToSlice(viewport.element, { imageIndex: index });

                }, framesPerSecond)
                // cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
            } else {
                if (this.toggleClipPlayTimer) {
                    clearInterval(this.toggleClipPlayTimer)
                    this.toggleClipPlayTimer = null
                }
                // cornerstoneTools.utilities.cine.stopClip(viewport.element)
            }
        },
        scrollPage(type) {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            const currentImageIdIndex = viewport.getCurrentImageIdIndex()
            const numImages = this.imageInfo.total
            let newImageIdIndex = null
            if (type === 0) {
                newImageIdIndex = 0
            } else if (type === -1) {
                newImageIdIndex = currentImageIdIndex === 0 ? currentImageIdIndex : currentImageIdIndex - 1
            } else if (type === 1) {
                newImageIdIndex = currentImageIdIndex === numImages - 1 ? currentImageIdIndex : currentImageIdIndex + 1
            } else if (type === 99999) {
                newImageIdIndex = numImages - 1
            }
            // viewport.setImageIdIndex(newImageIdIndex)
            csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex })
            cornerstoneTools.utilities.cine.stopClip(viewport.element)
        },
        setZoom(ratio) {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)

            const zoom = viewport.getZoom()
            if (ratio > 0) {
                viewport.setZoom(zoom * 1.05)
            } else {
                viewport.setZoom(zoom / 1.05)
            }
            viewport.render()
        },
        resize(forceFitToWindow) {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            if (!viewport) return
            let index = this.series.SliceIndex
            if (forceFitToWindow) {
                viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
                viewport.render()
                this.setFullScreen(index)
                return
            }

            viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
            const canvas = viewport.getCanvas() || this.element.querySelector('canvas')
            const imageData = viewport.getImageData()?.imageData
            const dimensions = imageData?.getDimensions()
            const imageWidth = dimensions?.[0]
            const imageHeight = dimensions?.[1]
            const canvasWidth = canvas?.clientWidth
            const canvasHeight = canvas?.clientHeight

            if (!imageWidth || !imageHeight || !canvasWidth || !canvasHeight) {
                viewport.render()
                this.setFullScreen(index)
                return
            }

            const fitScale = Math.min(canvasWidth / imageWidth, canvasHeight / imageHeight)
            if (fitScale > 0) {
                viewport.setZoom(1 / fitScale)
            }

            viewport.render()
            this.setFullScreen(index)
        },
        voiChange(v) {
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const voiRange = { lower: 0, upper: v }
            const viewport = renderingEngine.getViewport(this.viewportId)
            if (!viewport) return
            let volumeId = this.volumeId
            const viewportsContainingVolumeUID = csUtils.getViewportsWithVolumeId(
                volumeId,
                viewport.renderingEngineId
            )

            viewport.setProperties({ voiRange }, volumeId)
            viewportsContainingVolumeUID.forEach((vp) => {
                vp.render()
                // this.$refs[vp.id].voiModified()
                this.voiModified()
            })
        },
        setPreset(presetName) {
            this.presetName = presetName
        },
        async createImageIdsAndCacheMetaData(obj) {
            this.loading = true
            try {
                return await createImageIdsAndCacheMetaData({
                    modality: obj.Modality,
                    imageIds: obj.ImageIds
                })
            } finally {
                this.loading = false
            }
        },
        async setSeriesInfo(obj, isLocate = false) {
            try {
                let data = obj
                if (this.series && data.Id === this.series.Id && data.Description === this.series.Description && !isLocate && !data.isLocation) {
                    data.SliceIndex = this.series.SliceIndex
                }
                const renderingEngine = getRenderingEngine(this.renderingEngineId)
                const viewport = renderingEngine.getViewport(this.viewportId)
                if (isLocate) return csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex });
                this.series = {}
                this.volumeId = data.SeriesInstanceUid
                this.series = { ...data }
                viewport
                    .setVolumes([{
                        volumeId: this.volumeId, callback: (r) => {
                            if (this.series.Modality === 'PT') {
                                setPetTransferFunctionForVolumeActor(r)
                            } else {
                                let volume = cache.getVolume(this.volumeId)
                                const voi = metaData.get('voiLutModule', volume._imageIds[Math.ceil((volume._imageIds.length - 1) / 2)])
                                setCtMappingRange(voi.windowWidth[0], voi.windowCenter[0])
                                setCtTransferFunctionForVolumeActor(r)
                            }
                            console.log("渲染成功")
                        }
                    }]).then(r => {
                        if (data.isLocation || !this.imageInfo.zoom) {
                            setTimeout(() => { csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex }); })
                        }
                    })
                viewport.render()
                if (this.series.Modality === 'PT' || this.series.Modality === 'NM') {
                    setTimeout(() => {
                        // viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
                        // viewport.resetProperties()
                        viewport.setProperties({ voiRange: { upper: 5, lower: 0 }, invert: true }, this.volumeId)
                        viewport.render()
                    }, 100)
                }
                await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration, this.segmentationId, this.segmentIndex)
                DicomEvent.$emit('SegmentationLoading', this.viewportId)
                let volume = cache.getVolume(this.volumeId)
                // console.log(volume, 'volume')
                if (this.series.orientation === 'AXIAL' && this.series.curIndex) return this.setFullScreen(this.series.curIndex)
                console.log(this.series.orientation, this.series.curIndex)
                let index = this.series.orientation === 'AXIAL' ? Math.ceil((volume._imageIds.length - 1) / 2) - 1 : Math.ceil((volume.dimensions[0]) / 2) - 1
                this.setFullScreen(index)
            } catch (e) {
                console.log(e)
            }

        },
        cornerstoneToolsMouseMove(e) {
            const { currentPoints } = e.detail
            const worldPoint = currentPoints.world
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(this.viewportId)
            let referencedImageId = viewport.getCurrentImageId()
            const data = viewport.getImageData()
            if (!data) return
            const { dimensions, imageData, metadata, voxelManager } = data
            const index = imageData.worldToIndex(worldPoint)
            index[0] = Math.floor(index[0])
            index[1] = Math.floor(index[1])
            index[2] = Math.floor(index[2])
            this.mousePosition.index = index
            const modality = metadata.Modality
            let ijk = csUtils.transformWorldToIndex(imageData, worldPoint)
            ijk = vec3.round(ijk, ijk);
            if (csUtils.indexWithinDimensions(ijk, dimensions)) {
                this.isHandleOutsideImage = false
                let value = voxelManager.getAtIJKPoint(ijk)
                ijk[2] = viewport.getCurrentImageIdIndex()
                let modalityUnit
                if (modality === 'US') {
                    const calibratedResults = cornerstoneTools.utilities.getCalibratedProbeUnitsAndValue(data, [ijk])
                    const hasEnhancedRegionValues = calibratedResults.values.every(
                        (value) => value !== null
                    )
                    value = (hasEnhancedRegionValues ? calibratedResults.values : value)
                    modalityUnit = hasEnhancedRegionValues
                        ? calibratedResults.units
                        : 'raw';
                } else {
                    const scalingModule = referencedImageId && metaData.get('scalingModule', referencedImageId)
                    const isSuvScaled = typeof scalingModule?.suvbw === 'number'
                    if (scalingModule && scalingModule.suvbw) {
                        const pixelUnitsOptions = {
                            isPreScaled: cornerstoneTools.utilities.viewport.isViewportPreScaled(viewport, referencedImageId),
                            isSuvScaled: isSuvScaled,
                        }
                        modalityUnit = cornerstoneTools.utilities.getPixelValueUnits(
                            modality,
                            referencedImageId,
                            pixelUnitsOptions
                        );
                    }

                }
                this.mousePosition.value = value
                this.mousePosition.modalityUnit = modalityUnit
            }
        },
        toggleTask(evt, visitTaskNum, i) {
            this.$emit('activeViewport', this.viewportIndex)
            const num = visitTaskNum + i
            if (num >= 0 && num <= this.taskInfo.VisitNum) {
                this.$emit('toggleTaskByViewport', { series: this.series, visitTaskNum: num })
            }

            evt.stopImmediatePropagation()
            evt.stopPropagation()
            evt.preventDefault()
        },
        viewCD(taskId) {
            this.$emit('previewCD', taskId)
        },
        setWwwcIdx(idx) {
            this.wwwcIdx = idx
        },
        clickSlider(e) {
            const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
            this.sliderInfo.height = height
            let sliceIdx = Math.trunc(this.imageInfo.total * height / 100)
            sliceIdx = sliceIdx >= this.imageInfo.total ? this.imageInfo.total : sliceIdx < 0 ? 0 : sliceIdx
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(
                this.viewportId
            )
            // viewport.setImageIdIndex(sliceIdx)
            csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
            viewport.render()
        },
        sliderMouseup(e) {
            this.sliderInfo.isMove = false
            this.$emit('contentMouseup', e)
        },
        sliderMousedown(e) {
            const 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
            const delta = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
            const boxHeight = this.$refs['sliderBox'].clientHeight
            if (delta < 0) return
            if (delta > boxHeight) return
            const height = delta * 100 / boxHeight
            let sliceIdx = Math.trunc(this.imageInfo.total * height / 100)
            sliceIdx = sliceIdx >= this.imageInfo.total ? this.imageInfo.total - 1 : sliceIdx < 0 ? 0 : sliceIdx
            this.sliderInfo.height = height
            const renderingEngine = getRenderingEngine(this.renderingEngineId)
            const viewport = renderingEngine.getViewport(
                this.viewportId
            )
            // viewport.setImageIdIndex(sliceIdx)
            csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
            viewport.render()
        },
        sliderMouseleave(e) {
            if (!this.sliderInfo.isMove) return
            this.sliderInfo.isMove = false
        },
        rotate(angle) {
            let renderingEngine = getRenderingEngine(this.renderingEngineId)
            let viewport = renderingEngine.getViewport(this.viewportId)
            const camera = viewport.getCamera()
            const { viewUp, position, focalPoint } = camera
            const [cx, cy, cz] = focalPoint
            const [ax, ay, az] = [0, 0, 1]
            const newPosition = [0, 0, 0]
            const newFocalPoint = [0, 0, 0]
            const newViewUp = [0, 0, 0]

            const transform = mat4.identity(new Float32Array(16))
            mat4.translate(transform, transform, [cx, cy, cz])
            mat4.rotate(transform, transform, angle, [ax, ay, az])
            mat4.translate(transform, transform, [-cx, -cy, -cz])
            vec3.transformMat4(newPosition, position, transform)
            vec3.transformMat4(newFocalPoint, focalPoint, transform)

            mat4.identity(transform)
            mat4.rotate(transform, transform, angle, [ax, ay, az])
            vec3.transformMat4(newViewUp, viewUp, transform)

            viewport.setCamera({
                position: newPosition,
                viewUp: newViewUp,
                focalPoint: newFocalPoint
            })

            viewport.render()
        },
        clickRotate(e) {
            // console.log('clickRotate')
            const container = document.getElementById('rotateBar')
            const containerWidth = container.offsetWidth
            const slider = document.getElementById('rotateSlider')
            const sliderWidth = slider.offsetWidth
            const x = Math.trunc(e.offsetX)
            const deltaX = x - this.rotateBarLeft
            const angle = Math.sin((deltaX * (360 / (containerWidth - sliderWidth))) * Math.PI / 180)
            this.rotate(angle)
            this.rotateBarLeft = x
        },
        preventDefault(e) {
            e.stopImmediatePropagation()
            e.stopPropagation()
            e.preventDefault()
        }
    },
    computed: {
        NSTip() {
            return `NS: ${this.$store.state.trials.downloadTip}`
        }
    },
    destroyed() {
        if (this.toggleClipPlayTimer) {
            clearInterval(this.toggleClipPlayTimer)
            this.toggleClipPlayTimer = null
        }
    }
}
</script>
<style lang="scss" scoped>
.colorBar {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin: auto;
}

.viewport-wrapper {
    width: 100%;
    height: 100%;
    position: relative;
    cursor: default !important;

    .left-top-text {
        position: absolute;
        left: 5px;
        top: 5px;
        // color: #ddd; 
        z-index: 1;
        font-size: 12px;

        .cd-info {
            // color: #ddd; 
            font-size: 18px;
        }

        .subject-info {
            color: #f44336;
            padding: 5px 0px;
            margin: 0;
        }
    }

    .top-center-tool {
        position: absolute;
        left: 50%;
        top: 5px;
        transform: translateX(-50%);
        z-index: 1;

        .toggle-visit-container {
            display: flex;
        }

        .arrw_icon {
            width: 20px;
            height: 20px;
            background-color: #3f3f3f;
            text-align: center;
            line-height: 20px;
            border-radius: 10%;
        }

        .arrow_text {
            height: 20px;
            line-height: 20px;
            background-color: #00000057;
            color: #fff;
            padding: 0 10px;
            font-size: 14px;
        }
    }

    .right-top-text {
        position: absolute;
        right: 5px;
        top: 5px;
        // color: #ddd;
        z-index: 1;
        font-size: 12px;
    }

    .left-bottom-text {
        position: absolute;
        left: 5px;
        bottom: 5px;
        // color: #ddd;
        z-index: 1;
        font-size: 12px;
    }

    .right-bottom-text {
        position: absolute;
        right: 5px;
        bottom: 5px;
        // color: #ddd;
        z-index: 1;
        font-size: 12px;
    }

    .right-slider-box {
        position: absolute;
        right: 1px;
        height: calc(100% - 140px);
        transform: translateY(-50%);
        top: calc(50% - 30px);
        width: 10px;
        background: #333;
        z-index: 1;
        cursor: pointer;
    }

    .right-slider-box:after {
        content: '';
        position: absolute;
        bottom: -20px;
        left: 0;
        height: 20px;
        width: 100%;
        background: #333;
    }

    .slider {
        height: 20px;
        width: 100%;
        position: absolute;
        top: 0;
        z-index: 10;
        background: #9e9e9e;
        cursor: move
    }

    .orientation-top {
        position: absolute;
        left: 50%;
        top: 30px;
        color: #f44336;
        transform: translateX(-50%);
        z-index: 1;
    }

    .orientation-bottom {
        position: absolute;
        left: 50%;
        bottom: 15px;
        color: #f44336;
        transform: translateX(-50%);
        z-index: 1;
    }

    .orientation-left {
        position: absolute;
        top: 50%;
        left: 15px;
        color: #f44336;
        transform: translateY(-50%);
        z-index: 1;
    }

    .orientation-right {
        position: absolute;
        top: 50%;
        right: 15px;
        color: #f44336;
        transform: translateY(-50%);
        z-index: 1;
    }
}

.color_bar {
    position: absolute;
    transform: rotate(-90deg);
    transform-origin: right;
    left: -150px;
    top: 30%;
    z-index: 1;
}

.rotate_slider_box {
    position: absolute;
    width: 380px;
    height: 10px;
    bottom: 5px;
    left: 50%;
    transform: translateX(-50%);
    background: #333;
    z-index: 10;
    cursor: pointer;

    .box {
        z-index: 10;
        background: #9e9e9e;
        height: 100%;
        width: 20px;
        position: absolute;
        top: 0;
        cursor: move
    }
}
</style>
