<template>
  <custom-modal v-model="visible" :width="1280" title="Interactive Analyse Tools" :footer="null" destroy-on-close>
    <a-spin :spinning="isLoading">
      <div class="interactive-analysis-tools">
        <div class="interactive-analysis-tools-left">
          <div class="chart">
            <CustomChart ref="chartRef" :option="option" :opts="opts" @zr:click="handleChartClick" />
          </div>
          <!-- 缩略图 -->
          <div class="thumbnail">
            <CustomChart :option="thumbnailOption" />
          </div>
          <!-- 缩略图结束 -->

          <!-- 表格 -->
          <div class="table">
            <p class="title">
              <span @click="handleChangeMarkLine('prev')">&lt; </span>
              6 Peaks with Anthro.Nuclides
              <span @click="handleChangeMarkLine('next')">&gt;</span>
            </p>
            <custom-table
              :class="list.length ? 'has-data' : ''"
              :list="list"
              :columns="columns"
              :scroll="{ y: 288 }"
              :selectedRowKeys.sync="selectedKeys"
              rowKey="index"
              :canDeselect="false"
              @rowClick="handleTableRowClick"
            >
            </custom-table>
            <div class="operators">
              <a-button type="primary" @click="nuclideReviewModalVisible = true">Nuclide Review Window</a-button>
              <a-button type="primary" @click="handleAddComment('Peak')">Add Peak Comment</a-button>
              <a-button type="primary" @click="handleAddComment('General')">Add General Comment</a-button>
            </div>
          </div>
          <!-- 表格结束 -->
        </div>

        <!-- 右侧 -->
        <div class="interactive-analysis-tools-right">
          <title-over-border :title="btnGroupType == 1 ? 'Peak' : 'Baseline Control Points'">
            <div class="peak-box">
              <!-- 按钮组1 -->
              <template v-if="btnGroupType == 1">
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleInsert">Insert</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleDel">Delete</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleFit">Fit</a-button>
                </div>

                <div class="peak-box-item symbol" :key="4">
                  <a-button type="primary" @click="handleChangeMarkLine('prev')">&lt;</a-button>
                  <a-button type="primary" @click="handleChangeMarkLine('next')">&gt;</a-button>
                </div>

                <div class="peak-box-item base-line">
                  <a-button type="primary" @click="handleSwitchOperation">BaseLine</a-button>
                </div>
              </template>
              <!-- 按钮组2 -->
              <template v-if="btnGroupType == 2">
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleAddCP">(A)dd CP</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary">(R)emove CP</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary">(M)odify CP</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary">Edit (S)lope</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary">Undo</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary">Replot</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleAccept">Accept</a-button>
                </div>
                <div class="peak-box-item">
                  <a-button type="primary" @click="handleSwitchOperation">Cancel</a-button>
                </div>
              </template>
            </div>
          </title-over-border>
          <div class="reset-btn-box">
            <a-button type="primary">Reset Chart</a-button>
          </div>
          <div class="identify-box">
            <title-over-border title="Nuclide Identify">
              <a-form-model class="tolerance">
                <a-form-model-item label="Tolerance">
                  <a-input-number v-model="model.tolerance"></a-input-number>
                </a-form-model-item>
              </a-form-model>
              <div class="identify-item">
                <div class="title">
                  Possible Nuclide
                </div>
                <div class="content">
                  <template v-if="selectedTableItem && selectedTableItem._possible">
                    <div
                      class="item"
                      :class="{ active: possible == model.possibleNuclide }"
                      v-for="(possible, index) in selectedTableItem._possible"
                      :key="index"
                      @click="model.possibleNuclide = possible"
                    >
                      {{ possible }}
                    </div>
                  </template>
                </div>
              </div>
              <div class="identify-item">
                <div class="title">
                  Nuclide Identified
                </div>
                <div class="content">
                  <template v-if="selectedTableItem">
                    <div
                      class="item"
                      :class="{ active: identified == model.identifiedNuclide }"
                      v-for="(identified, index) in selectedTableItem.nuclides"
                      :key="index"
                      @click="model.identifiedNuclide = identified"
                    >
                      {{ identified }}
                    </div>
                  </template>
                </div>
              </div>
              <div class="identify-operators">
                <span class="text">{{ model.possibleNuclide }}</span>
                <a-button type="primary" :disabled="!model.possibleNuclide" @click="handleAddNuclide">Add</a-button>
                <a-button type="primary" @click="handleDelNuclide">Del</a-button>
              </div>
            </title-over-border>
          </div>
        </div>
        <!-- 右侧结束 -->
      </div>
    </a-spin>
    <!-- Comment弹窗 开始 -->
    <comment-modal v-model="commentModalVisible" :type="commentType" />
    <!-- Comment弹窗 结束 -->
    <!-- Fit Peaks and Baseline弹窗 开始 -->
    <fit-peaks-and-base-line-modal v-model="fitPeaksAndBaselineModalVisible" />
    <!-- Fit Peaks and Baseline弹窗 结束 -->
    <!-- Nuclide Review 弹窗开始 -->
    <nuclide-review-modal v-model="nuclideReviewModalVisible" :sampleId="sampleId" :channel="currChannel" />
    <!-- Nuclide Review 弹窗结束 -->
  </custom-modal>
</template>

<script>
import CustomChart from '@/components/CustomChart/index.vue'
import TitleOverBorder from '../../TitleOverBorder.vue'
import CommentModal from './components/CommentModal.vue'
import FitPeaksAndBaseLineModal from './components/FitPeaksAndBaselineModal.vue'
import NuclideReviewModal from './components/NuclideReviewModal.vue'
import ModalMixin from '@/mixins/ModalMixin'
import { getAction } from '@/api/manage'
import { cloneDeep } from 'lodash'
import Response from './Response.json'
import { findSeriesByName, getXAxisAndYAxisByPosition } from '@/utils/chartHelper'
import SampleDataMixin from '@/views/spectrumAnalysis/SampleDataMixin'

// 初始配置
const initialOption = {
  grid: {
    top: 40,
    left: 40,
    right: 30,
    bottom: 30,
    containLabel: true
  },
  title: {
    text: '',
    left: 'center',
    bottom: 10,
    textStyle: {
      color: '#8FD4F8',
      rich: {
        a: {
          padding: [0, 20, 0, 0],
          fontSize: 16
        }
      }
    }
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      lineStyle: {
        color: '#3CAEBB',
        width: 1
      }
    },
    formatter: params => {
      const [channel] = params[0].value
      return `<div class="channel">Channel: ${channel}</div>
              <div class="energy">Energy: ${(0).toFixed(2)}</div>`
    },
    className: 'figure-chart-option-tooltip'
  },
  xAxis: {
    axisLine: {
      lineStyle: {
        color: '#ade6ee'
      }
    },
    splitLine: {
      show: false
    },
    axisLabel: {
      textStyle: {
        color: '#ade6ee'
      }
    },
    min: 1,
    max: 'dataMax',
    animation: false
  },
  yAxis: {
    name: 'Counts',
    nameLocation: 'center',
    nameGap: 40,
    nameTextStyle: {
      color: '#8FD4F8',
      fontSize: 16
    },
    axisLine: {
      show: true,
      lineStyle: {
        color: '#ade6ee'
      }
    },
    splitLine: {
      show: true,
      lineStyle: {
        color: 'rgba(173, 230, 238, .2)'
      }
    },
    axisLabel: {
      textStyle: {
        color: '#ade6ee'
      }
    },
    min: 'dataMin',
    max: 'dataMax',
    animation: false
  },
  series: [],
  brush: {}
}

const columns = [
  {
    title: 'ID',
    customRender: (_, __, index) => {
      return index + 1
    },
    width: 60
  },
  {
    title: 'Energy (keV)',
    dataIndex: 'energy',
    width: 120
  },
  {
    title: 'Centroid (C)',
    dataIndex: 'peakCentroid',
    width: 120
  },
  {
    title: 'FWHM (keV)',
    dataIndex: 'fwhm',
    width: 120
  },
  {
    title: 'Area',
    dataIndex: 'area',
    width: 120
  },
  {
    title: 'Detectability',
    dataIndex: 'detectability',
    width: 120
  },
  {
    title: 'Cmnt',
    dataIndex: 'cmnt',
    width: 120
  },
  {
    title: 'Nuclides',
    dataIndex: 'nuclides',
    width: 120,
    customRender: text => {
      return text && text.join(';')
    }
  }
]

// 缩略图配置
const thumbnailOption = {
  grid: {
    top: 0,
    left: 5,
    right: 5,
    bottom: 0
  },
  xAxis: {
    type: 'category',
    axisLine: {
      show: false
    },
    splitLine: {
      show: false
    },
    axisLabel: {
      show: false
    },
    min: 1,
    max: 'dataMax'
  },
  yAxis: {
    type: 'value',
    axisLine: {
      show: false
    },
    splitLine: {
      show: false
    },
    axisLabel: {
      show: false
    },
    min: 1
  },
  series: []
}
export default {
  mixins: [ModalMixin, SampleDataMixin],
  components: {
    CustomChart,
    TitleOverBorder,
    CommentModal,
    FitPeaksAndBaseLineModal,
    NuclideReviewModal
  },
  data() {
    this.columns = columns
    return {
      option: cloneDeep(initialOption),
      opts: { notMerge: false },
      thumbnailOption: cloneDeep(thumbnailOption),

      isLoading: false,
      list: [],
      sampleId: -1,

      commentModalVisible: false, // Comment 弹窗是否显示
      commentType: 'Peak',

      btnGroupType: 1, // 右侧 Peak 中的按钮组切换

      selectedKeys: [], // 选中的列表

      fitPeaksAndBaselineModalVisible: false, // Fit Peaks And Base Line 弹窗
      nuclideReviewModalVisible: false, // Nuclide Review 弹窗

      model: {
        possibleNuclide: '',
        tolerance: 0.5,
        identifiedNuclide: ''
      },

      currChannel: undefined, // 当currChannel前选中的channel
      selectedTableItem: undefined // 当前选中的表格项
    }
  },
  methods: {
    async getInfo() {
      try {
        this.isLoading = true
        this.option.series = []

        const { success, result, message } = Response
        // const { success, result, message } = await getAction('/gamma/InteractiveTool', {
        //   sampleId: this.sampleId,
        //   fileName: this.fileName
        // })
        if (success) {
          const {
            barChart,
            channelBaseCPChart,
            channelBaseLineChart,
            channelCountChart,
            channelPeakChart,
            table
          } = result
          this.isLoading = false

          console.log('%c [  ]-374', 'font-size:13px; background:pink; color:#bf2c9f;', result)

          this.channelPeakChart = channelPeakChart

          const series = []

          // 推入BaseLine
          series.push({
            ...this.buildSeriesOption(
              'BaseLine',
              channelBaseLineChart.pointlist.map(({ x, y }) => [x, y]),
              `rgb(${channelBaseLineChart.color})`
            ),
            markLine: {
              silent: true,
              symbol: 'none',
              label: {
                show: false
              },
              lineStyle: {
                color: 'red',
                width: 1
              },
              data: [{ xAxis: -1 }]
            },
            zlevel: 10
          })

          // 推入Count
          series.push(
            this.buildSeriesOption(
              'CountChart',
              channelCountChart.pointlist.map(({ x, y }) => [x, y]),
              `rgb(${channelCountChart.color})`
            )
          )

          // 推入Peak
          const peakSeries = []
          channelPeakChart.forEach((item, index) => {
            peakSeries.push(
              this.buildSeriesOption(
                'Peak_' + (index + 1),
                item.pointlist.map(({ x, y }) => [x, y]),
                `rgb(${item.color})`
              )
            )
          })

          series.push(...peakSeries)

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

          this.thumbnailOption.series.push(
            this.buildSeriesOption(
              'BarChart',
              barChart.map(({ x, y }) => [x, y]),
              '#fff',
              {
                silent: true
              }
            )
          )

          this.list = table
          this.option.series = series
        } else {
          this.$message.error(message)
        }
      } catch (error) {
        console.error(error)
      }
    },

    // 构建series
    buildSeriesOption(name, data, color, extra = {}) {
      return {
        name,
        type: 'line',
        data,
        itemStyle: {
          color
        },
        lineStyle: {
          width: 1
        },
        symbol: 'none',
        symbolSize: 1,
        emphasis: {
          disabled: true
        },
        animation: false,
        ...extra
      }
    },

    beforeModalOpen() {
      const { sampleId, inputFileName } = this.sampleData
      this.sampleId = sampleId
      this.fileName = inputFileName

      this.currChannel = undefined
      this.btnGroupType = 1

      this.getInfo()
      this.opts.notMerge = false

      this.$nextTick(() => {
        this.option.brush = { toolbox: [] }
        this.selectedKeys = []
      })
    },

    // 点击图表，设置红线，改变表格的选中项
    handleChartClick(param) {
      const { offsetX, offsetY } = param
      const point = getXAxisAndYAxisByPosition(this.$refs.chartRef.getChartInstance(), offsetX, offsetY)
      if (point) {
        const xAxis = parseInt(point[0].toFixed())
        this.option.series[0].markLine.data[0].xAxis = xAxis

        this.currChannel = xAxis

        // 获取每一段 Channel 中的最大值
        const maxXAxises = this.getPeakMaxValues()

        let index = 0
        // 计算当前选中的xAxis跟哪条 peak的最大值 最近
        if (xAxis >= maxXAxises[maxXAxises.length - 1]) {
          index = maxXAxises.length - 1
        } else if (xAxis <= maxXAxises[0]) {
          index = 0
        } else {
          for (let i = 1; i < maxXAxises.length; i++) {
            const prev = maxXAxises[i - 1]
            const curr = maxXAxises[i]

            if (xAxis >= prev && xAxis <= curr) {
              index = xAxis - prev < curr - xAxis ? i - 1 : i
              break
            }
            continue
          }
        }

        const selectedRow = this.list[index]

        this.selectedKeys = [selectedRow.index]

        this.getSelPosNuclide(selectedRow)
      }
    },

    // 切换图表上的红色竖线及表格选中
    handleChangeMarkLine(direction) {
      const markLineOption = this.option.series[0].markLine.data[0]
      const prevAxis = markLineOption.xAxis

      // 获取每一段 Channel 中的最大值
      const maxXAxises = this.getPeakMaxValues()
      if (direction == 'next') {
        // 找到第一个比prevAxis大的xAxis
        const find = maxXAxises.find(xAxis => xAxis > prevAxis)
        if (find) {
          markLineOption.xAxis = find
        }
      } else if (direction == 'prev') {
        // 找到第一个比prevAxis小的xAxis
        const find = cloneDeep(maxXAxises)
          .reverse()
          .find(xAxis => xAxis < prevAxis)
        if (find) {
          markLineOption.xAxis = find
        }
      }

      const xAxis = markLineOption.xAxis
      if (xAxis >= 0) {
        const index = maxXAxises.findIndex(item => item == xAxis)
        if (index !== -1) {
          this.selectedKeys = [this.list[index].index]
        }
      }
    },

    // 获取右下角possible nuclide 和 identified nuclide
    async getSelPosNuclide(row) {
      this.model.possibleNuclide = ''
      this.model.identifiedNuclide = ''

      if (!row._possible) {
        try {
          const { success, result, message } = await getAction('/gamma/getSelPosNuclide', {
            sampleId: this.sampleId,
            channel: parseInt(row.peakCentroid),
            nuclides: row.nuclides.join(','),
            fileName: this.fileName
          })
          if (success) {
            const { possible } = result
            this.$set(row, '_possible', possible)
          } else {
            this.$message.error(message)
          }
        } catch (error) {
          console.error(error)
        }
      }
    },

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

    // 显示comment弹窗
    handleAddComment(type) {
      this.commentType = type
      this.commentModalVisible = true
    },

    // Insert按钮
    handleInsert() {
      this.fitPeaksAndBaselineModalVisible = true
    },

    // 删除
    handleDel() {
      if (!this.selectedKeys.length) {
        this.$message.warn('No peak to delete.')
        return
      }

      this.$warning({
        title: 'Warning',
        content: 'Are you sure to delete this peak?',
        onOk: () => {
          const [willDelKey] = this.selectedKeys
          const findIndex = this.list.findIndex(item => item.index == willDelKey)
          this.list.splice(findIndex, 1)
          this.selectedKeys = []

          const seriesIndex = this.option.series.findIndex(item => {
            return item.name == 'Peak_' + willDelKey
          })

          this.opts.notMerge = true
          this.option.series.splice(seriesIndex, 1)
          this.channelPeakChart.splice(findIndex, 1)

          this.$nextTick(() => {
            this.opts.notMerge = false
            this.option.brush = { toolbox: [] }
          })
        }
      })
    },

    // 匹配
    handleFit() {
      if (!this.list.length) {
        this.$message.warn('No peak to fit.')
        return
      }
    },

    // 表格的行点击
    handleTableRowClick(row) {
      if (this.selectedTableItem == row) {
        return
      }

      const channel = row.peakCentroid
      this.currChannel = channel

      this.option.series[0].markLine.data[0].xAxis = channel

      this.getSelPosNuclide(row)

      this.selectedTableItem = row
    },

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

    // 切换操作
    handleSwitchOperation() {
      // 切换到Base Line 和 Control Point 操作
      if (this.btnGroupType == 1) {
        this.btnGroupType = 2

        const originalCPSeries = findSeriesByName(this.option.series, 'BaseLine')
        this.option.series.push(
          this.buildSeriesOption('Edit_BaseLine', originalCPSeries.data, '#fff', {
            zlevel: 21
          })
        )
      }
      // 切换回 Peak 操作
      else {
        this.btnGroupType = 1
        this.option.series.splice(this.option.series.length - 1, 1)
      }
    },

    // 在当前选中的红线位置新增控制点
    handleAddCP() {
      const xAxis = this.option.series[0].markLine.data[0].xAxis

      if (xAxis == -1) {
        this.$message.warn("Can't insert Control Point out of range")
        return
      }

      console.log('%c [  ]-735', 'font-size:13px; background:pink; color:#bf2c9f;', xAxis)
    },

    // 确定对Control Point 的操作
    handleAccept() {},

    // 右下角添加当前选中的nuclide
    handleAddNuclide() {
      const nuclides = this.selectedTableItem.nuclides
      const possibleNuclide = this.model.possibleNuclide
      if (this.selectedTableItem && !nuclides.includes(possibleNuclide)) {
        nuclides.push(possibleNuclide)
      }
    },
    // 右下角删除当前选中的nuclide
    handleDelNuclide() {
      const [willDelKey] = this.selectedKeys
      const find = this.list.find(item => item.index == willDelKey)
      console.log('%c [ find ]-762', 'font-size:13px; background:pink; color:#bf2c9f;', find)
      if (find) {
        const nuclides = find.nuclides
        const findIndex = nuclides.findIndex(nuclide => nuclide == this.model.identifiedNuclide)
        if (-1 !== findIndex) {
          nuclides.splice(findIndex, 1)
        }
      }
    }
  }
}
</script>

<style lang="less" scoped>
.interactive-analysis-tools {
  display: flex;

  &-left {
    width: 75%;
    margin-right: 20px;

    .chart {
      height: 331px;
    }

    .thumbnail {
      height: 50px;
      margin: 10px 10px 35px 40px;
      background-color: #255369;
    }

    .table {
      .title {
        color: #0cebc9;
        font-size: 20px;
        text-align: center;
        margin-bottom: 10px;
        user-select: none;

        span {
          cursor: pointer;
          margin: 0 5px;
        }
      }

      .custom-table {
        &.has-data {
          ::v-deep {
            .ant-table-body {
              height: 288px;
              background-color: #06282a;
            }
          }
        }

        ::v-deep {
          .ant-table-placeholder {
            height: 289px;
            display: flex;
            justify-content: center;
            align-items: center;
          }
        }
      }

      .operators {
        display: flex;
        margin-top: 10px;
        gap: 10px;

        .ant-btn {
          flex: 1;
        }
      }
    }
  }

  &-right {
    .peak-box {
      height: 326px;

      &-item:not(:last-child) {
        margin-bottom: 10px;
      }

      .symbol {
        display: flex;

        .ant-btn {
          flex: 1;

          &:first-child {
            margin-right: 10px;
          }
        }
      }
    }

    .base-line {
      margin-top: 136px;
    }

    .reset-btn-box {
      margin-top: 20px;
      margin-bottom: 30px;
    }

    .identify-box {
      .tolerance {
        ::v-deep {
          .ant-form-item {
            margin-bottom: 10px;

            &-control-wrapper {
              flex: 1;
            }

            &-control {
              width: 100%;
            }
          }
        }

        .ant-input-number {
          width: 100%;
        }
      }

      .identify-item {
        .title {
          background-color: #497e9d;
          height: 30px;
          line-height: 30px;
          text-align: center;
          font-size: 16px;
        }

        .content {
          height: 80px;
          background-color: #275466;
          margin: 10px 0;
          padding: 5px;
          overflow: auto;

          .item {
            cursor: pointer;
            line-height: 26px;
            padding: 0 5px;

            &.active {
              background: #296d81;
            }
          }
        }
      }

      .identify-operators {
        display: flex;
        gap: 10px;
        .text {
          flex: 1;
          line-height: 32px;
          background-color: #285366;
          padding: 0 10px;
        }

        .ant-btn {
          width: 50px;
          padding-left: 5px;
          padding-right: 5px;
        }
      }
    }
  }

  .ant-btn {
    width: 100%;
  }
}
</style>
