<template>
  <div class="gamma-analysis">
    <a-spin :spinning="isLoading">
      <!-- 二级交互栏 -->
      <div class="spectrum-analysis-sub-operators">
        <pop-over-with-icon placement="bottomLeft">
          Detailed-Information
          <detailed-infomation slot="content" :data="detailedInfomation" />
        </pop-over-with-icon>
        <pop-over-with-icon placement="bottomLeft">
          QC Flags
          <qc-flags slot="content" :data="qcFlags" />
        </pop-over-with-icon>
        <pop-over-with-icon>
          Graph Assistance
          <graph-assistance
            v-if="!isLoading"
            slot="content"
            @change="handleGraphAssistanceChange"
            @reset="handleResetChart"
          />
        </pop-over-with-icon>
        <a-popover
          overlayClassName="popover-with-icon"
          :visible="nuclideLibraryVisible"
          @click="handleChangeNuclideVisible"
          placement="bottom"
        >
          <div class="pop-over-with-icon">
            <span class="text"> Nuclide Library </span>
            <img src="@/assets/images/global/select-down.png" alt="" />
          </div>
          <a-spin slot="content" :spinning="isLoadingNuclide">
            <nuclide-library :list="nuclideLibraryList" @dblclick="handleNuclideDblClick" />
          </a-spin>
        </a-popover>

        <div class="peak-info">
          <button-with-switch-icon @change="handlePeakInfoChange" @click="handleTogglePeak"></button-with-switch-icon>
        </div>
      </div>
      <!-- 二级交互栏结束 -->
      <!-- 主体部分 -->
      <div class="gamma-analysis-main">
        <div class="gamma-analysis-chart">
          <CustomChart
            ref="chartRef"
            :option="option"
            :opts="opts"
            @zr:click="handleChartClick"
            @zr:dblclick="handleChartDblClick"
            @zr:mousedown="handleMouseDown"
            @zr:mouseup="handleMouseUp"
            @brushEnd="handleBrushEnd"
            style="height: 100%"
          />
          <!-- 右上角缩略图 -->
          <div class="gamma-analysis-thumbnail">
            <CustomChart
              ref="thumbnailChartRef"
              :option="thumbnailOption"
              @zr:click="handleThumbnailChartClick"
              style="height: 100%"
            />
          </div>
          <!-- 缩略图结束 -->

          <!-- 自定义tooltip，用于展示Peak Infomation -->
          <div
            v-if="peakInfomationTooltip.visible"
            class="peak-infomation-tooltip"
            :style="{
              top: peakInfomationTooltip.top + 'px',
              left: peakInfomationTooltip.left + 'px',
            }"
          >
            <div class="peak-infomation-tooltip-content" v-html="peakInfomationTooltip.content"></div>
          </div>
          <!-- tooltip结束 -->
        </div>
      </div>
      <!-- 主体部分结束 -->
    </a-spin>

    <nuclide-review-modal
      v-model="nuclideReview.visible"
      :sampleId="sample.sampleId"
      :channel="currChannel"
      :nuclide="nuclideReview.nuclide"
    />

    <compare-file-list-modal v-model="compareFileListModalVisible" @fileSelect="handleFileSelect" />

    <!-- Strip 弹窗开始 -->
    <strip-modal ref="stripModal" />
    <!-- Strip 弹窗结束 -->

    <!-- ReProcessing 弹窗开始 -->
    <re-processing-modal
      v-if="abc"
      v-model="reprocessingModalVisible"
      :bAnalyed="bAnalyed"
      :currStep="currStep"
      :checkBoxFlag="checkBox_updateCal"
      :newCheckBoxFlag="newCheckBox_updateCal"
      @closeModal="haCndleCloseModal"
    />
    <!-- ReProcessing 弹窗结束 -->
  </div>
</template>

<script>
import CustomChart from '@/components/CustomChart/index.vue'
import PopOverWithIcon from './components/SubOperators/PopOverWithIcon.vue'
import DetailedInfomation from './components/SubOperators/DetailedInfomation.vue'
import QcFlags from './components/SubOperators/QcFlags.vue'
import GraphAssistance from './components/SubOperators/GraphAssistance.vue'
import NuclideLibrary from './components/SubOperators/NuclideLibrary.vue'
import ButtonWithSwitchIcon from './components/SubOperators/ButtonWithSwitchIcon.vue'
import { getAction, postAction } from '@/api/manage'
import Response from './response.json'
import {
  buildLineSeries,
  findSeriesByName,
  getAxisMax,
  getXAxisAndYAxisByPosition,
  rangeNumber,
} from '@/utils/chartHelper'
import { cloneDeep } from 'lodash'
import axios from 'axios'
import NuclideReviewModal from './components/Modals/AnalyzeInteractiveToolModal/components/NuclideReviewModal.vue'
import CompareFileListModal from './components/Modals/CompareFileListModal.vue'
import ReProcessingModal from './components/Modals/ReProcessingModal/index.vue'

import { GammaOptions, graphAssistance } from './settings'

import store from '@/store/'
import Vue from 'vue'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import StripModal from './components/Modals/StripModal.vue'

export default {
  props: {
    sample: {
      type: Object,
    },
    updateFlag: {
      type: String,
    },
  },
  components: {
    CustomChart,
    PopOverWithIcon,
    DetailedInfomation,
    QcFlags,
    GraphAssistance,
    NuclideLibrary,
    ButtonWithSwitchIcon,
    NuclideReviewModal,
    CompareFileListModal,
    ReProcessingModal,
    StripModal,
  },
  data() {
    return {
      abc: false,
      isLoading: false,
      isLoadingNuclide: false,
      option: cloneDeep(GammaOptions.option),
      opts: {
        notMerge: false,
      },
      thumbnailOption: cloneDeep(GammaOptions.thumbnailOption),

      detailedInfomation: [],
      qcFlags: [],
      graphAssistance: cloneDeep(graphAssistance),
      nuclideLibraryVisible: false,

      channelData: {
        peakGroup: [],
        spectrumLine: null,
        baseLine: null,
        lcLine: null,
        scacLine: null,
        all: null,
        baseLineCP: [],
      },
      energyData: {
        peakGroup: [],
        spectrumLine: null,
        baseLine: null,
        lcLine: null,
        scacLine: null,
        all: null,
        baseLineCP: [],
      },

      nuclideLibraryList: [], // 当前鼠标点击选中的channel
      peakInfomationTooltip: {
        // Peak Infomation的位置
        visible: false,
        content: '',
        top: 0,
        left: 0,
      },

      nuclideReview: {
        visible: false,
        nuclide: '',
      },
      currChannel: -1,

      compareFileListModalVisible: false, // Compare 弹窗
      isStrip: false,

      reprocessingModalVisible: false, // 重新分析弹窗
      isProcessing: false, // 正在处理
      websock: null,
      lockReconnect: false,
      bAnalyed: false, //是否重新分析
      checkBox_updateCal: false, //update复选框状态
      newCheckBox_updateCal: false, //update复选框状态
      currStep: '',
    }
  },
  created() {
    this.setChartBottomTitle(0, 0, 0)
    this.option.tooltip.formatter = this.tooltipFormatter

    this.$bus.$on('colorChange', this.handleColorChange)
    this.$bus.$on('gammaRefresh', this.handleRefresh)
    this.$bus.$on('accept', this.handleAccept)
  },
  destroyed() {
    this.cancelLastRequest()

    this.$bus.$off('colorChange', this.handleColorChange)
    this.$bus.$off('gammaRefresh', this.handleRefresh)
    this.$bus.$off('accept', this.handleAccept)
  },
  mounted() {
    this.option.brush = { toolbox: [] }
    this.initWebSocket()
  },
  methods: {
    initWebSocket: function () {
      console.log('qweqwerq')
      // WebSocket与普通的请求所用协议有所不同，ws等同于http，wss等同于https
      var userId = store.getters.userInfo.id
      var url =
        window._CONFIG['domianURL'].replace('https://', 'wss://').replace('http://', 'ws://') + '/websocket/' + userId
      //console.log(url);
      //update-begin-author:taoyan date:2022-4-22 for:  v2.4.6 的 websocket 服务端，存在性能和安全问题。 #3278
      let token = Vue.ls.get(ACCESS_TOKEN)
      this.websock = new WebSocket(url, [token])
      //update-end-author:taoyan date:2022-4-22 for:  v2.4.6 的 websocket 服务端，存在性能和安全问题。 #3278
      this.websock.onopen = this.websocketOnopen
      this.websock.onerror = this.websocketOnerror
      this.websock.onmessage = this.websocketOnmessage
      this.websock.onclose = this.websocketOnclose
    },
    websocketOnopen: function () {
      // console.log('WebSocket连接成功1231')
      //心跳检测重置
      //this.heartCheck.reset().start();
    },
    websocketOnerror: function (e) {
      this.reconnect()
    },
    websocketOnmessage: function (e) {
      // console.log('-----接收消息1231-------', e.data)
      var data = eval('(' + e.data + ')') //解析对象
      // console.log(data)
      if (data.cmd === 'analysis-process') {
        this.currStep = data.msgTxt
      }
    },
    websocketOnclose: function (e) {
      this.reconnect()
    },
    reconnect() {
      var that = this
      if (that.lockReconnect) return
      that.lockReconnect = true
      //没连接上会一直重连，设置延迟避免请求过多
      setTimeout(function () {
        console.info('尝试重连...')
        that.initWebSocket()
        that.lockReconnect = false
      }, 20000)
    },
    // 获取样品详情
    async getSampleDetail() {
      const { dbName, sampleId } = this.sample
      try {
        this.isLoading = true

        this.handleResetState()

        // const { success, result, message } = Response
        this.cancelLastRequest()
        const cancelToken = this.createCancelToken()

        const { success, result, message } = await getAction(
          '/gamma/gammaByDB',
          {
            dbName,
            sampleId,
          },
          cancelToken
        )
        console.log('%c [ result ]-243', 'font-size:13px; background:pink; color:#bf2c9f;', result)
        if (success) {
          this.dataProsess(result, 'db')
        } else {
          this.$message.error(message)
          this.isLoading = false
        }
      } catch (error) {
        console.error(error)
        this.isLoading = false
      }
    },

    async getSampleDetail_file() {
      const { inputFileName: fileName } = this.sample
      try {
        this.isLoading = true
        this.handleResetState()
        // const { success, result, message } = Response

        this.cancelLastRequest()
        const cancelToken = this.createCancelToken()

        const { success, result, message } = await getAction(
          '/gamma/gammaByFile',
          {
            fileName,
          },
          cancelToken
        )
        console.log('%c [ result ]-243', 'font-size:13px; background:pink; color:#bf2c9f;', result)
        if (success) {
          this.dataProsess(result, 'file')
        } else {
          this.$message.error(message)
          this.isLoading = false
        }
      } catch (error) {
        console.error(error)
        this.isLoading = false
      }
    },

    cancelLastRequest() {
      if (this._cancelToken && typeof this._cancelToken == 'function') {
        this._cancelToken()
      }
    },

    createCancelToken() {
      const cancelToken = new axios.CancelToken((c) => {
        this._cancelToken = c
      })
      return cancelToken
    },

    dataProsess(result, flag) {
      this.isLoading = false

      const {
        dead_time,
        live_time,
        real_time,
        start_time,

        DetailedInformation,
        QCFlag,

        allData,

        shadowChannelChart,
        shadowEnergyChart,

        shapeChannelData,
        shapeEnergyData,
      } = result
      if (flag && (flag == 'dab' || flag == 'file')) {
        this.bAnalyed = result.bAnalyed
        this.checkBox_updateCal = result.checkBox_updateCal
        this.newCheckBox_updateCal = '2'
        console.log(this.checkBox_updateCal)
      }
      this.detailedInfomation = DetailedInformation
      this.qcFlags = QCFlag

      const channelPeakGroup = this.getLineData(allData, 'Peak', 'channel', true)
      const energyPeakGroup = this.getLineData(allData, 'Peak', 'energy', true)

      const channelBaseLine = this.getLineData(allData, 'BaseLine', 'channel')
      const energyBaseLine = this.getLineData(allData, 'BaseLine', 'energy')

      const channelLcLine = this.getLineData(allData, 'Lc', 'channel')
      const energyLcLine = this.getLineData(allData, 'Lc', 'energy')

      const channelScacLine = this.getLineData(allData, 'Scac', 'channel')
      const energyScacLine = this.getLineData(allData, 'Scac', 'energy')

      const allChannel = this.getLineData(allData, 'Count', 'channel')
      const allEnergy = this.getLineData(allData, 'Energy', 'energy')

      this.channelData = {
        peakGroup: channelPeakGroup,
        spectrumLine: shadowChannelChart,
        baseLine: channelBaseLine,
        lcLine: channelLcLine,
        scacLine: channelScacLine,
        all: allChannel,
        baseLineCP: shapeChannelData,
      }

      this.energyData = {
        peakGroup: energyPeakGroup,
        spectrumLine: shadowEnergyChart,
        baseLine: energyBaseLine,
        lcLine: energyLcLine,
        scacLine: energyScacLine,
        all: allEnergy,
        baseLineCP: shapeEnergyData,
      }

      this.resetThumbnailChartDataMax()
      const series = []

      // 推入Spectrum Line
      series.push(
        buildLineSeries(
          'Spectrum',
          this.transformPointListData(shadowChannelChart.pointlist),
          shadowChannelChart.color,
          {
            symbolSize: 2,
            markLine: {
              silent: true,
              symbol: 'none',
              label: {
                show: false,
              },
              lineStyle: {
                color: 'red',
                width: 1,
              },
              data: [{ xAxis: -1 }],
            },
          }
        )
      )

      // 右上角缩略图设置Spectrum Line 数据
      this.setSeriesData(
        this.thumbnailOption.series,
        'Spectrum',
        this.transformPointListData(shadowChannelChart.pointlist),
        shadowChannelChart.color
      )

      // 推入BaseLine
      series.push(
        buildLineSeries('BaseLine', this.transformPointListData(channelBaseLine.pointlist), channelBaseLine.color, {
          zlevel: 2,
        })
      )

      // 推入LcLine线
      series.push(
        buildLineSeries('LcLine', this.transformPointListData(channelLcLine.pointlist), channelLcLine.color, {
          zlevel: 3,
        })
      )

      // 推入Scac线
      series.push(
        buildLineSeries('ScacLine', this.transformPointListData(channelScacLine.pointlist), channelScacLine.color, {
          zlevel: 4,
        })
      )

      // 推入基线控制点
      series.push({
        name: 'BaseLine_Ctrl_Point',
        type: 'scatter',
        data: shapeChannelData.map(({ size, color, point: { x, y } }) => {
          return {
            value: [x, y],
            itemStyle: {
              color: 'transparent',
              borderColor: color,
              borderWidth: size / 2,
            },
          }
        }),
        emphasis: {
          disabled: true,
        },
        animation: false,
        zlevel: 5,
      })

      // 推入Peak Line
      const peakLines = []
      channelPeakGroup.forEach((item, index) => {
        peakLines.push(
          buildLineSeries(`Peak_${index}`, this.transformPointListData(item.pointlist), item.color, {
            zlevel: 6,
          })
        )
      })
      series.push(...peakLines)

      // 推入Compare Line
      series.push(
        buildLineSeries('Compare', [], '#fff', {
          symbolSize: 2,
        })
      )

      this.option.series = series
    },

    // chart 的 tooltip
    tooltipFormatter(params) {
      let channel = 0
      let energy = 0
      const value = params[0].value[0]

      if (this.isEnergy()) {
        energy = value.toFixed(2)
        channel = this.getChannelByEnergy(energy)
      } else {
        const allPointList = this.energyData.all.pointlist
        channel = parseInt(value.toFixed())
        energy = allPointList && allPointList[channel - 1]
        energy = energy ? energy.x.toFixed(2) : undefined
      }

      return `<div class="channel">Channel: ${channel}</div>
              <div class="energy">${energy ? `Energy: ${energy}` : ''}</div>`
    },

    // Graph Assistance 操作
    handleGraphAssistanceChange({ type, label, value }) {
      const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
      const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      const compareLineSeries = findSeriesByName(this.option.series, 'Compare')

      // 类型变化
      if (type == 'labelChange') {
        switch (label) {
          case 'Linear':
            this.option.yAxis.type = 'value'
            this.thumbnailOption.yAxis.type = 'value'
            this.handleResetChart()
            break
          case 'Log10':
            this.option.yAxis.type = 'log'
            this.thumbnailOption.yAxis.type = 'log'
            this.handleResetChart()
            break
          case 'Channel':
          case 'Energy':
            this.graphAssistance.axisType = label
            this.option.xAxis.name = label

            this.handleResetChart()

            this.redrawLineBySeriesName(
              'BaseLine',
              this.energyData.baseLine,
              this.channelData.baseLine,
              this.graphAssistance.Baseline
            )
            this.redrawLineBySeriesName(
              'LcLine',
              this.energyData.lcLine,
              this.channelData.lcLine,
              this.graphAssistance.Lc
            )
            this.redrawLineBySeriesName(
              'ScacLine',
              this.energyData.scacLine,
              this.channelData.scacLine,
              this.graphAssistance.SCAC
            )

            this.redrawLineBySeriesName('Spectrum', this.energyData.spectrumLine, this.channelData.spectrumLine)
            this.redrawCtrlPointBySeriesName()
            this.redrawPeakLine()

            this.redrawThumbnailChart()

            if (this.channelCompareLine) {
              this.redrawLineBySeriesName('Compare', this.energyCompareLine, this.channelCompareLine)
            }
            break
          case 'Lines':
            this.graphAssistance.spectrumType = 'Lines'

            spectrumLineSeries.type = 'line'
            spectrumLineSeries.symbol = 'none'

            thumbnailSpectrumLineSeries.type = 'line'
            thumbnailSpectrumLineSeries.symbol = 'none'

            compareLineSeries.type = 'line'
            compareLineSeries.symbol = 'none'

            this.redrawLineBySeriesName('Spectrum', this.energyData.spectrumLine, this.channelData.spectrumLine)

            if (this.channelCompareLine) {
              this.redrawLineBySeriesName('Compare', this.energyCompareLine, this.channelCompareLine)
            }
            break
          case 'Scatter':
            this.graphAssistance.spectrumType = 'Scatter'

            spectrumLineSeries.type = 'scatterGL'
            spectrumLineSeries.symbol = 'circle'

            thumbnailSpectrumLineSeries.type = 'scatterGL'
            thumbnailSpectrumLineSeries.symbol = 'circle'

            compareLineSeries.type = 'scatterGL'
            compareLineSeries.symbol = 'circle'

            this.$nextTick(() => {
              this.rangeScatter()
            })
            break
        }
      }
      // 值变化
      else if (type == 'valueChange') {
        this.graphAssistance[label] = value

        switch (label) {
          case 'Cursor':
            // 显示红色竖线
            if (value) {
              spectrumLineSeries.markLine.lineStyle.width = 2
            } else {
              spectrumLineSeries.markLine.lineStyle.width = 0
            }
            break
          case 'Baseline':
            this.redrawLineBySeriesName('BaseLine', this.energyData.baseLine, this.channelData.baseLine, value)
            break
          case 'Lc':
            this.redrawLineBySeriesName('LcLine', this.energyData.lcLine, this.channelData.lcLine, value)
            break
          case 'SCAC':
            this.redrawLineBySeriesName('ScacLine', this.energyData.scacLine, this.channelData.scacLine, value)
            break
        }
      }
    },

    handleChangeNuclideVisible() {
      this.nuclideLibraryVisible = !this.nuclideLibraryVisible
    },

    // 根据seriesName重绘线
    redrawLineBySeriesName(seriesName, energyData, channelData, isShow = true, color) {
      if (isShow) {
        const data = this.isEnergy() ? energyData : channelData
        this.setSeriesData(this.option.series, seriesName, this.transformPointListData(data.pointlist), color)
      } else {
        this.setSeriesData(this.option.series, seriesName, [])
      }
    },

    // 重绘控制点
    redrawCtrlPointBySeriesName() {
      const series = findSeriesByName(this.option.series, 'BaseLine_Ctrl_Point')
      const data = this.isEnergy() ? this.energyData.baseLineCP : this.channelData.baseLineCP
      series.data = data.map(({ size, color, point: { x, y } }) => {
        return {
          value: [x, y],
          itemStyle: {
            color: 'transparent',
            borderColor: color,
            borderWidth: size / 2,
          },
        }
      })
    },

    // 重绘Peak Line
    redrawPeakLine() {
      this.option.series = this.option.series.filter((item) => {
        return !item.name.includes('Peak_')
      })

      const data = this.isEnergy() ? this.energyData.peakGroup : this.channelData.peakGroup
      const peakLines = []
      data.forEach((item, index) => {
        peakLines.push(
          buildLineSeries(`Peak_${index}`, this.transformPointListData(item.pointlist), item.color, {
            zlevel: 6,
          })
        )
      })

      this.option.series.push(...peakLines)
    },

    // 重绘右上角的缩略图
    redrawThumbnailChart() {
      const series = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      const data = this.isEnergy() ? this.energyData.spectrumLine : this.channelData.spectrumLine
      series.data = this.transformPointListData(data.pointlist)
    },

    // 点击图表，设置红线
    handleChartClick(param) {
      const { offsetX, offsetY } = param
      const point = getXAxisAndYAxisByPosition(this.getChart(), offsetX, offsetY)
      if (point) {
        const xAxis = point[0]
        const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
        spectrumLineSeries.markLine.data[0].xAxis = xAxis

        const { channel, energy, counts } = this.getEnergyAndCountsByXAxis(xAxis)
        this.setChartBottomTitle(channel, energy, counts)

        this.getSelPosNuclide(channel)
      }
    },

    // 设置图表底部的标题
    setChartBottomTitle(channel, energy, counts) {
      this.option.title.text = `{a|Channel:${channel}} {a|Energy:${energy}} {a|Counts:${counts}} {a|Detectability:0}`
    },

    // 根据xAixs值找channel、energy和counts
    getEnergyAndCountsByXAxis(xAxis) {
      let channel, energy, counts
      if (this.isEnergy()) {
        channel = this.getChannelByEnergy(xAxis)
        energy = xAxis.toFixed(2)
        counts = this.energyData.all.pointlist[channel - 1]
      } else {
        channel = parseInt(xAxis.toFixed())
        energy = this.energyData.all.pointlist && this.energyData.all.pointlist[channel - 1].x.toFixed(2)
        counts = this.channelData.all.pointlist[channel - 1]
      }
      return {
        channel,
        energy,
        counts: counts.y,
      }
    },

    // 双击还原
    handleChartDblClick() {
      this.handleResetChart()
    },

    // 获取 Nuclide Library 数据
    async getSelPosNuclide(channel) {
      this.currChannel = channel

      try {
        this.isLoadingNuclide = true
        const { sampleId, inputFileName: fileName } = this.sample

        const { success, result, message } = await getAction('/gamma/getSelPosNuclide', {
          sampleId,
          channel,
          fileName,
        })
        if (success) {
          const { possible } = result
          this.nuclideLibraryList = possible
        } else {
          this.$message.error(message)
        }
      } catch (error) {
        this.list = []
        console.error(error)
      } finally {
        this.isLoadingNuclide = false
      }
    },

    // Nuclide Library 单项双击
    handleNuclideDblClick(nuclide) {
      this.nuclideLibraryVisible = false
      this.nuclideReview.nuclide = nuclide
      this.nuclideReview.visible = true
    },

    resize() {
      this.$refs.chartRef.resize()
      this.$refs.thumbnailChartRef.resize()
      this.closePeakInfomationTooltip()
    },

    // peak info 点击左右方向
    handlePeakInfoChange(direction) {
      this.moveMarkLine(direction)
    },

    // 触发Peak Infomation
    handleTogglePeak() {
      const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
      const xAxis = spectrumLineSeries.markLine.data[0].xAxis
      const channel = this.isEnergy() ? this.getChannelByEnergy(xAxis) : parseInt(xAxis.toFixed())
      const index = this.channelData.peakGroup.findIndex((peakItem) => {
        const allX = peakItem.pointlist.map((item) => item.x)
        const max = Math.max(...allX)
        const min = Math.min(...allX)
        return channel >= min && channel <= max
      })
      if (-1 !== index) {
        this.getPeakInfo(index)
      } else {
        this.closePeakInfomationTooltip()
      }
    },

    // 获取 Peak 峰顶 信息
    async getPeakInfo(index) {
      try {
        const { inputFileName: fileName } = this.sample
        const { success, result, message } = await getAction('/gamma/clickPeakInformation', {
          fileName,
          index,
        })
        if (success) {
          const html = result.replaceAll('\n', '<br>')
          const currPeak = this.channelData.peakGroup[index]
          const { x, y } = currPeak.pointlist.reduce((prev, curr) => {
            return prev && prev.y > curr.y ? prev : curr
          })

          const [xPix, yPix] = this.getChart().convertToPixel({ seriesIndex: 0 }, [x, y])
          this.peakInfomationTooltip.content = html
          this.peakInfomationTooltip.visible = true
          this.peakInfomationTooltip.left = xPix
          this.peakInfomationTooltip.top = yPix - 20
        } else {
          this.$message.error(message)
        }
      } catch (error) {
        console.error(error)
      }
    },

    // 关闭Peak Infomation
    closePeakInfomationTooltip() {
      this.peakInfomationTooltip.visible = false
    },

    /**
     * 向某一个方向移动标记线
     * @param { 'left'| 'right' } direction
     */
    moveMarkLine(direction) {
      const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
      const prevAxis = spectrumLineSeries.markLine.data[0].xAxis

      // 获取每一段 Channel 中的最大值
      const maxXAxises = this.channelData.peakGroup.map((item) => {
        const allY = item.pointlist.map((item) => item.y)
        const max = item.pointlist.find((point) => point.y == Math.max(...allY))
        return max.x
      })

      let find = null
      if (direction == 'right') {
        // 找到第一个比prevAxis大的xAxis
        find = maxXAxises.find((xAxis) => xAxis > prevAxis)
        if (find) {
          spectrumLineSeries.markLine.data[0].xAxis = find
        }
      } else if (direction == 'left') {
        // 找到第一个比prevAxis小的xAxis
        find = maxXAxises.reverse().find((xAxis) => xAxis < prevAxis)
        if (find) {
          spectrumLineSeries.markLine.data[0].xAxis = find
        }
      }

      if (find) {
        this.getSelPosNuclide(find)
        const { channel, energy, counts } = this.getEnergyAndCountsByXAxis(find)
        this.setChartBottomTitle(channel, energy, counts)
      }
    },

    // 鼠标按下时开启可刷选状态
    handleMouseDown() {
      this.getChart().dispatchAction({
        type: 'takeGlobalCursor',
        // 如果想变为“可刷选状态”，必须设置。不设置则会关闭“可刷选状态”。
        key: 'brush',
        brushOption: {
          // 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
          brushType: 'rect',
        },
      })
    },

    handleMouseUp() {
      if (this.timer) {
        window.clearTimeout(this.timer)
      }
      this.timer = setTimeout(() => {
        this.clearBrush()
      }, 0)
    },

    clearBrush() {
      const chart = this.getChart()
      // 清理刷选的范围
      chart.dispatchAction({
        type: 'brush',
        areas: [],
      })

      // 改为不可刷选状态
      chart.dispatchAction({
        type: 'takeGlobalCursor',
      })
    },

    // 刷选完毕时
    handleBrushEnd(param) {
      this.closePeakInfomationTooltip()

      const chart = this.$refs.chartRef.getChartInstance()
      const areas = param.areas[0]
      if (areas) {
        const range = areas.range
        const [[minX, maxX], [minY, maxY]] = range

        const point1 = chart.convertFromPixel({ seriesIndex: 0 }, [minX, minY]).map((num) => parseInt(num.toFixed()))
        const point2 = chart.convertFromPixel({ seriesIndex: 0 }, [maxX, maxY]).map((num) => parseInt(num.toFixed()))

        // 拿到之前的最大值
        const xAxisMax = getAxisMax(chart, 'xAxis')
        const yAxisMax = getAxisMax(chart, 'yAxis')

        // 拿到之前的最小值
        const xAxisMin = this.option.xAxis.min
        const yAxisMin = this.option.yAxis.min

        let [x1, y2, x2, y1] = [...point1, ...point2] // 根据解析出的数据确定真实的范围

        const xAxisLimit = rangeNumber(xAxisMin, xAxisMax)
        const yAxisLimit = rangeNumber(yAxisMin, yAxisMax)

        x1 = xAxisLimit(x1)
        x2 = xAxisLimit(x2)

        y1 = yAxisLimit(y1)
        y2 = yAxisLimit(y2)

        this.option.xAxis.min = x1
        this.option.xAxis.max = x2
        this.option.yAxis.min = y1
        this.option.yAxis.max = y2

        if (this.isEnergy()) {
          const channel1 = this.getChannelByEnergy(x1)
          const channel2 = this.getChannelByEnergy(x2)
          this.setThumbnailChartRect(channel1, y2, channel2, y1)
        } else {
          this.setThumbnailChartRect(x1, y2, x2, y1)
        }

        const thumbnailChart = this.getThumbnailChart()
        const [, maxYPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, y1]) // 方框的上下两条边的yAxis转为pix
        const [, minYPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, y2])
        const rectHeightPixel = maxYPixel - minYPixel // 计算方框的左右边长(pix)
        this.halfHeightPixel = rectHeightPixel / 2
      }

      this.$nextTick(() => {
        this.rangeScatter()
      })
    },

    /**
     * 因scatterGL 不受axis中max和min的控制，手动处理溢出部分
     * @param {Boolean} isReset 是否重置到初始状态
     */
    rangeScatter(isReset) {
      if (!this.isScatter()) {
        return
      }

      const {
        xAxis: { min: x1 },
        yAxis: { min: y1 },
      } = this.option

      const chart = this.getChart()
      const x2 = getAxisMax(chart, 'xAxis')
      const y2 = getAxisMax(chart, 'yAxis')

      const channelSpectrumData = {
        ...this.channelData.spectrumLine,
        pointlist: isReset
          ? this.pointlistLimitY(this.channelData.spectrumLine.pointlist)
          : this.pointlistLimit(this.channelData.spectrumLine.pointlist, x1, x2, y1, y2),
      }
      const energySpectrumData = {
        ...this.energyData.spectrumLine,
        pointlist: isReset
          ? this.pointlistLimitY(this.energyData.spectrumLine.pointlist)
          : this.pointlistLimit(this.energyData.spectrumLine.pointlist, x1, x2, y1, y2),
      }
      this.redrawLineBySeriesName('Spectrum', energySpectrumData, channelSpectrumData)

      if (this.channelCompareLine) {
        const channelCompareLine = {
          ...this.channelCompareLine,
          pointlist: isReset
            ? this.pointlistLimitY(this.channelCompareLine.pointlist)
            : this.pointlistLimit(this.channelCompareLine.pointlist, x1, x2, y1, y2),
        }
        const energyCompareLine = {
          ...this.energyCompareLine,
          pointlist: isReset
            ? this.pointlistLimitY(this.energyCompareLine.pointlist)
            : this.pointlistLimit(this.energyCompareLine.pointlist, x1, x2, y1, y2),
        }
        this.redrawLineBySeriesName('Compare', energyCompareLine, channelCompareLine)
      }
    },

    /**
     * 筛选范围内的点
     * @param {*} pointlist
     * @param {*} x1
     * @param {*} x2
     * @param {*} y1
     * @param {*} y2
     */
    pointlistLimit(pointlist, x1, x2, y1, y2) {
      return pointlist.filter(({ x, y }) => x >= x1 && x <= x2 && y >= y1 && y <= y2)
    },

    pointlistLimitY(pointlist) {
      return pointlist.filter(({ y }) => y >= 1)
    },

    // 在右上角缩略图中设置范围
    setThumbnailChartRect(x1, y2, x2, y1) {
      this.thumbnailChartRect = [x1, y2, x2, y1]

      const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      const { markLine } = thumbnailSpectrumLineSeries
      const pointList = [
        [
          [x1, y1],
          [x2, y1],
        ],
        [
          [x2, y1],
          [x2, y2],
        ],
        [
          [x2, y2],
          [x1, y2],
        ],
        [
          [x1, y2],
          [x1, y1],
        ],
      ]
      const lines = pointList.map((point) => {
        return this.generateLineDataByTwoPoints(point[0], point[1])
      })
      markLine.data = lines
    },

    // 缩略图点击
    handleThumbnailChartClick(param) {
      const { offsetX, offsetY } = param
      const thumbnailChart = this.getThumbnailChart()

      const point = getXAxisAndYAxisByPosition(thumbnailChart, offsetX, offsetY)
      if (point && this.thumbnailChartRect && this.thumbnailChartRect.length) {
        const [x1, y2, x2, y1] = this.thumbnailChartRect
        const halfWidth = Math.ceil((x2 - x1) / 2)

        // 缩略图最大值转为pix
        const [, maxYAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [
          0,
          getAxisMax(thumbnailChart, 'yAxis'),
        ])
        const [, minYAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, 1])

        let [xAxis, yAxis] = point

        const xAxisMax = getAxisMax(thumbnailChart, 'xAxis')

        const xAxisLimit = rangeNumber(1 + halfWidth, xAxisMax - halfWidth)

        const halfHeightPixel = this.halfHeightPixel
        const yAxisLimit = rangeNumber(maxYAxisPixel + halfHeightPixel, minYAxisPixel - halfHeightPixel)

        xAxis = xAxisLimit(xAxis)

        let [, yAxisPixel] = thumbnailChart.convertToPixel({ seriesIndex: 0 }, [0, yAxis])
        yAxisPixel = yAxisLimit(yAxisPixel)

        const minYAxis = thumbnailChart.convertFromPixel({ seriesIndex: 0 }, [0, yAxisPixel + halfHeightPixel])[1] // 再把y轴最小值从pix转为yAxis
        const maxYAxis = thumbnailChart.convertFromPixel({ seriesIndex: 0 }, [0, yAxisPixel - halfHeightPixel])[1]

        this.setThumbnailChartRect(xAxis - halfWidth, maxYAxis, xAxis + halfWidth, minYAxis)

        if (this.isEnergy()) {
          const x1 = parseInt(this.energyData.spectrumLine.pointlist[xAxis - halfWidth].x)
          const x2 = parseInt(this.energyData.spectrumLine.pointlist[xAxis + halfWidth].x)

          this.option.xAxis.min = x1
          this.option.xAxis.max = x2
        } else {
          this.option.xAxis.min = xAxis - halfWidth
          this.option.xAxis.max = xAxis + halfWidth
        }

        this.option.yAxis.min = minYAxis
        this.option.yAxis.max = maxYAxis

        this.$nextTick(() => {
          this.rangeScatter()
        })
      }
    },

    /**
     * 重置图表
     */
    handleResetChart() {
      this.option.xAxis.min = 1
      this.option.xAxis.max = 'dataMax'
      this.option.yAxis.min = 1
      this.option.yAxis.max = 'dataMax'

      const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      thumbnailSpectrumLineSeries.markLine.data = []
      this.thumbnailChartRect = []
      this.closePeakInfomationTooltip()

      this.$nextTick(() => {
        this.rangeScatter(true)
      })
    },

    // 从分析工具刷新部分数据
    handleRefresh(data) {
      this.handleResetState()
      data.DetailedInformation = this.detailedInfomation
      this.clearCompareLine()
      this.dataProsess(data)
    },

    // 分析工具Accept时刷新部分数据
    handleAccept(data) {
      console.log('%c [ data ]-1166', 'font-size:13px; background:pink; color:#bf2c9f;', data)
      const {
        allData,
        barChart,
        channelBaseLineChart,
        peakSet,
        shadowChannelChart,
        shadowEnergyChart,
        shapeChannelData,
        shapeData,
        shapeEnergyData,
      } = data

      this.clearCompareLine()
      this.channelData.peakGroup = this.getLineData(allData, 'Peak', 'channel', true)
      this.energyData.peakGroup = this.getLineData(allData, 'Peak', 'energy', true)
      this.redrawPeakLine()

      this.channelData.baseLine = this.getLineData(allData, 'BaseLine', 'channel')
      this.energyData.baseLine = this.getLineData(allData, 'BaseLine', 'energy')
      this.redrawLineBySeriesName(
        'BaseLine',
        this.energyData.baseLine,
        this.channelData.baseLine,
        this.graphAssistance.Baseline
      )

      this.channelData.baseLineCP = shapeChannelData
      this.energyData.baseLineCP = shapeEnergyData
      this.redrawCtrlPointBySeriesName()
    },

    // 显示比较弹窗
    showCompareModal(isStrip) {
      if (this.isLoading) {
        this.$message.warn('Sample is Loading')
        return
      }
      this.handleResetChart()
      this.clearCompareLine()
      this.compareFileListModalVisible = true

      this.isStrip = isStrip
    },

    // 文件之间对比
    async handleFileSelect(selectedFileName) {
      const { inputFileName: fileName } = this.sample

      try {
        let param = {
            fileName,
            compareFileName: selectedFileName,
          },
          url = '/gamma/Compare'
        // 如果是Strip
        if (this.isStrip) {
          const ratio = await this.$refs.stripModal.getRatio()

          param = {
            fileName,
            stripFileName: selectedFileName,
            ratioRate: ratio || 1,
          }
          url = '/gamma/Strip'
        }

        this.isLoading = true
        const { success, result, message } = await getAction(url, param)
        if (success) {
          const [channelData, energyData] = result
          this.channelCompareLine = channelData
          this.energyCompareLine = energyData
          this.redrawLineBySeriesName('Compare', energyData, channelData, true, channelData.color)

          if (this.isScatter()) {
            lineSeries.type = 'scatterGL'
          }

          this.$nextTick(() => {
            this.thumbnailOption.yAxis.max = getAxisMax(this.getChart(), 'yAxis')
          })
        } else {
          this.$message.error(message)
        }
      } catch (error) {
        console.error(error)
      } finally {
        this.isLoading = false
      }
    },

    // 移除 Compare 线
    clearCompareLine() {
      const compareLine = findSeriesByName(this.option.series, 'Compare')
      if (compareLine) {
        compareLine.data = []
        this.resetThumbnailChartDataMax()
      }
      this.channelCompareLine = undefined
      this.energyCompareLine = undefined
    },

    // 重新分析
    async reProcessing() {
      if (this.isProcessing) {
        return
      }

      if (this.isLoading) {
        this.$message.warn('Sample is Loading')
        return
      }

      try {
        this.isLoading = true
        const { inputFileName: fileName } = this.sample
        const { success, result, message } = await postAction(`/gamma/Reprocessing?fileName=${fileName}`)
        if (success) {
          this.handleResetState()
          result.DetailedInformation = this.detailedInfomation
          this.dataProsess(result)
        } else {
          this.isLoading = false
          const arr = message.split('\n')
          this.$warning({
            title: 'Warning',
            content: () => arr.map((text) => <div>{text}</div>),
          })
        }
      } catch (error) {
        console.error(error)
      } finally {
        this.isLoading = false
      }
    },
    haCndleCloseModal() {
      this.reprocessingModalVisible = false
      this.abc = false
    },

    /**
     * 重置缩略图表y轴最大值
     */
    resetThumbnailChartDataMax() {
      this.thumbnailOption.yAxis.max = 'dataMax'
    },

    /**
     * 重置图表配置
     */
    resetChartOpts() {
      this.opts.notMerge = false
      this.option.brush = { toolbox: [] }
    },

    /**
     * 根据两个点生成一个markLine直线
     */
    generateLineDataByTwoPoints(point1, point2) {
      return [
        {
          xAxis: point1[0],
          yAxis: point1[1],
        },
        {
          xAxis: point2[0],
          yAxis: point2[1],
        },
      ]
    },

    /**
     * 根据energy获取channel
     * @param {number} energy
     */
    getChannelByEnergy(energy) {
      let channel = 0
      const pointlist = this.energyData.all.pointlist
      for (let index = 1; index < pointlist.length; index++) {
        const currEnergy = pointlist[index].x
        if (currEnergy >= energy) {
          const prevEnergy = pointlist[index - 1].x
          if (currEnergy - energy > energy - prevEnergy.x) {
            channel = index
          } else {
            channel = index + 1
          }
          break
        }
      }
      return channel
    },

    /**
     * 重置页面信息
     */
    handleResetState() {
      this.handleResetChart()

      this.selectedChannel = -1
      this.nuclideLibraryList = []
      this.closePeakInfomationTooltip()
      this.option.series = []
      this.option.xAxis.name = 'Channel'
      this.option.yAxis.type = 'value'
      this.thumbnailOption.yAxis.type = 'value'

      if (this.option.series.length) {
        const spectrumLineSeries = findSeriesByName(this.option.series, 'Spectrum')
        spectrumLineSeries.type = 'line'
        spectrumLineSeries.symbol = 'none'
        spectrumLineSeries.markLine.lineStyle.width = 2
      }

      const thumbnailSpectrumLineSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      thumbnailSpectrumLineSeries.type = 'line'
      thumbnailSpectrumLineSeries.symbol = 'none'

      this.graphAssistance = cloneDeep(graphAssistance)
    },

    /**
     * 颜色改变
     * @param {*} colorConfig
     */
    handleColorChange(colorConfig) {
      // 如果还没加载完，加载新的
      if (this.isLoading) {
        this.getSampleDetail()
      }
      // 否则修改已有颜色
      else {
        this.changeColor(colorConfig)
      }
    },

    // 修改颜色
    changeColor(colorConfig) {
      const { Color_Spec, Color_Peak, Color_Lc, Color_Base, Color_Scac, Color_Compare, Color_Strip, Color_Fitbase } =
        colorConfig

      this.channelData.spectrumLine.color = Color_Spec
      this.energyData.spectrumLine.color = Color_Spec

      for (let i = 0; i < this.channelData.peakGroup.length; i++) {
        this.channelData.peakGroup[i].color = Color_Peak
        this.energyData.peakGroup[i].color = Color_Peak
      }

      this.channelData.lcLine.color = Color_Lc
      this.energyData.lcLine.color = Color_Lc

      this.channelData.baseLine.color = Color_Base
      this.energyData.baseLine.color = Color_Base

      this.channelData.scacLine.color = Color_Scac
      this.energyData.scacLine.color = Color_Scac

      if (this.channelCompareLine) {
        this.channelCompareLine.color = Color_Compare
        this.energyCompareLine.color = Color_Compare
      }

      this.changeColorBySeriesName('Spectrum', Color_Spec)
      this.changePeakLineColor(Color_Peak)
      this.changeColorBySeriesName('LcLine', Color_Lc)
      this.changeColorBySeriesName('BaseLine', Color_Base)
      this.changeColorBySeriesName('ScacLine', Color_Scac)
      this.changeColorBySeriesName('Compare', Color_Compare)

      const thumbnailChartSeries = findSeriesByName(this.thumbnailOption.series, 'Spectrum')
      thumbnailChartSeries.itemStyle.color = Color_Spec
    },

    /**
     * 根据series名修改颜色
     * @param {*} seriesName
     * @param {*} color
     */
    changeColorBySeriesName(seriesName, color) {
      const series = findSeriesByName(this.option.series, seriesName)
      series.itemStyle.color = color
    },

    // 改变Peak的颜色
    changePeakLineColor(color) {
      this.option.series
        .filter((item) => item.name.includes('Peak_'))
        .forEach((item) => {
          item.itemStyle.color = color
        })
    },

    isEnergy() {
      return this.graphAssistance.axisType == 'Energy'
    },

    isScatter() {
      return this.graphAssistance.spectrumType == 'Scatter'
    },

    getChart() {
      return this.$refs.chartRef.getChartInstance()
    },

    getThumbnailChart() {
      return this.$refs.thumbnailChartRef.getChartInstance()
    },

    /**
     * 设置图表数据和颜色
     */
    setSeriesData(series, seriesName, data, color) {
      const find = findSeriesByName(series, seriesName)
      find.data = data
      if (color) {
        find.itemStyle.color = color
      }
    },

    /**
     * 转换pointlist类型数据到series的data可用的数据
     */
    transformPointListData(pointlist) {
      if (!pointlist) {
        return []
      }
      return pointlist.map(({ x, y }) => [x, y])
    },

    /**
     * 在返回的allData中查找指定的数据
     * @param {Array} allData
     * @param {*} name
     * @param {*} group
     */
    getLineData(allData, name, group, isList = false) {
      const arrFunc = isList ? Array.prototype.filter : Array.prototype.find
      return arrFunc.call(allData, (item) => item.name == name && item.group == group) || {}
    },
  },
  watch: {
    currStep: {
      handler(val) {
        if (val && val == '0') {
          this.abc = true
          this.reprocessingModalVisible = true
        }
      },
      immediate: true,
    },
    sample: {
      handler(newVal, oldVal) {
        console.log('newValnewVal', newVal)
        if (newVal.sampleId) {
          this.getSampleDetail()
        } else {
          this.getSampleDetail_file()
        }
      },
      immediate: true,
    },
    updateFlag: {
      handler(val) {
        this.newCheckBox_updateCal = val
      },
      immediate: true,
    },
  },
}
</script>

<style lang="less" scoped>
.gamma-analysis {
  height: 100%;

  .ant-spin-nested-loading {
    height: 100%;

    ::v-deep {
      .ant-spin-container {
        height: 100%;
      }
    }
  }

  &-main {
    height: calc(100% - 51px);
    display: flex;
    overflow: auto hidden;
    position: relative;
  }

  &-chart {
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
  }

  &-thumbnail {
    position: absolute;
    top: 50px;
    right: 10px;
    width: 500px;
    height: 20%;
    background-color: #153e44;
  }
}
</style>
<style lang="less">
.peak-infomation-tooltip {
  position: absolute;
  border-style: solid;
  white-space: nowrap;
  z-index: 9;
  box-shadow: rgba(0, 0, 0, 0.2) 1px 2px 10px;
  border-width: 1px;
  border-radius: 4px;
  padding: 10px;
  border-color: rgb(255, 255, 255);
  pointer-events: none;
  background-color: #55a9fe;
  border-color: #55a9fe;
}
</style>
