<template>
  <div>
    <el-card class="no-bottom">
      <el-form ref="form" :model="form" inline :rules="rules">
        <el-form-item label="设备类型:" prop="deviceType">
          <el-select v-model="form.deviceType" @change="onDeviceTypeChange">
            <el-option
              v-for="(deviceType, index) in deviceTypeList"
              :key="index"
              :label="deviceType.name"
              :value="deviceType.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="设备实例:" prop="deviceInstance">
          <el-select v-model="form.deviceInstance" placeholder="请选择">
            <el-option
              v-for="(deviceInstance, index) in deviceInstanceList"
              :key="index"
              :label="deviceInstance.name"
              :value="deviceInstance.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="数据模型:" prop="dataMode">
          <el-select v-model="form.dataMode" placeholder="请选择">
            <el-option
              v-for="(dataMode, index) in dataModelList"
              :key="index"
              :label="dataMode.name"
              :value="dataMode.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="采样数据:" prop="time">
          <el-select v-model="form.time" placeholder="请选择" style="width: 240px">
            <el-option
              v-for="(sample, index) in samplingList"
              :key="index"
              :label="$moment(sample.time, 'MM-DD HH:mm:ss')"
              :value="sample.time"
            >
              <span style="float: left">{{ $moment(sample.time, 'MM-DD HH:mm:ss') }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ sample.samplingRate }} MS/s</span>
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="queryData">查询</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card class="margin-top-20">
      <div slot="header">
        <span>采样信息</span>
      </div>
      <descriptions
        v-if="isSupported"
        label-position="top"
        label-width="80px"
        style="margin-left: 30px"
      >
        <descriptions-item label="采样率" value="">
          <div>{{ sampling.samplingRate }} MS/s</div>
        </descriptions-item>
        <descriptions-item label="数据总数" value="">
          <div>{{ property.data.series.length }}</div>
        </descriptions-item>
        <descriptions-item label="采样周期" value="">
          <div>{{ sampling.samplingPeriod }} us</div>
        </descriptions-item>
      </descriptions>
      <div v-else class="el-table__empty-text" style="text-align: center;margin: 0 auto">不支持频域分析</div>
    </el-card>

    <el-row :gutter="20">
      <el-col :span="16">
        <el-card class="margin-top-20">
          <div v-if="!isSupported" slot="header" class="clearfix">
            <span>图表</span>
          </div>
          <el-tabs v-if="isSupported" v-model="activeProperty">
            <el-tab-pane
              v-for="(property, index) in propertyList"
              :key="index"
              :label="property.propertyName"
              :name="property.propertyCode"
            />
          </el-tabs>
          <time-domain-line
            v-if="isSupported"
            :id="'line-' + property.propertyCode"
            ref="timeDomainLine"
            :title="property.propertyName"
            :step="property.propertyType === 4"
            :line-data="property.data"
            :description="property.propertyUnit"
            :config="lineConfig"
            :function-list="functionList"
            format="MM-DD HH:mm:ss"
            @datazoom="onDataZoom"
          />
          <div v-else class="el-table__empty-text" style="text-align: center;margin: 0 auto">不支持频域分析</div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="margin-top-20">
          <div slot="header">
            <span>FFT</span>
          </div>
          <fft-line
            v-if="isSupported"
            id="fft-chart"
            :line-data="fft.data"
            width="300"
          />
          <div v-else class="el-table__empty-text" style="text-align: center;margin: 0 auto">不支持频域分析</div>
        </el-card>
      </el-col>
    </el-row>

    <el-card class="margin-top-20">
      <div slot="header" class="clearfix">
        <span>分量</span>
      </div>
      <el-tabs v-if="isSupported" v-model="activeFunction">
        <el-tab-pane
          v-for="(func, index) in functionList"
          :key="index"
          :label="func.name"
          :name="func.id"
        />
      </el-tabs>
      <el-row v-if="isSupported" :gutter="20">
        <el-col :span="16">
          <function-line
            id="function-line"
            ref="functionLine"
            :line-data="functionChartData"
            :config="lineConfig"
            @datazoom="onDataZoom"
          />
        </el-col>
        <el-col :span="8">
          <descriptions
            title="Detail"
            label-position="top"
            label-width="80px"
            style="margin-left: 30px"
          >
            <descriptions-item :span="24" label="振幅" value="">
              <div>{{ functionChartDetail.amplitude }}</div>
            </descriptions-item>
            <descriptions-item :span="24" label="频率" value="">
              <div>{{ functionChartDetail.frequency }} Hz</div>
            </descriptions-item>
            <descriptions-item :span="24" label="相位" value="">
              <div>{{ functionChartDetail.phase }}</div>
            </descriptions-item>
          </descriptions>
        </el-col>
      </el-row>
      <div v-else class="el-table__empty-text" style="text-align: center;margin: 0 auto">不支持频域分析</div>
    </el-card>
  </div>
</template>

<script>
import { getAllDeviceModel } from '@/api/equipment-management/equipment-instance'
import { getAllInstanceByDeviceTypeId } from '@/api/equipment-management/equipment-model'
import { getDataModelByDeviceTypeId } from '@/api/equipment-management/equipment-model'
import FunctionLine from '@/components/Charts/FunctionLine'
import TimeDomainLine from '@/components/Charts/TimeDomainLine'
import FftLine from '@/components/Charts/FFtLine'
import moment from 'moment'
import { getTimeDomainData, getFrequencyDomainData, getDataPreview } from '@/api/device-management/frequency-analysis'
import { getPropertyDetail } from '@/api/equipment-management/device-instance'

export default {
  name: 'FrequencyAnalysis',
  components: {
    FunctionLine,
    TimeDomainLine,
    FftLine
  },
  data() {
    return {
      form: {
        deviceType: null,
        deviceInstance: null,
        dataMode: null,
        time: null
      },
      activeProperty: null,
      tableData: [],
      pageForm: {
        pageSize: 10,
        pageNum: 1,
        total: 0
      },
      deviceTypeList: [],
      deviceInstanceList: [],
      dataModelList: [],
      propertyList: [],
      lineConfig: {
        dataZoom: [
          {
            type: 'slider',
            realtime: true,
            start: 0,
            end: 5
          },
          {
            type: 'inside',
            realtime: true,
            start: 0,
            end: 5
          }
        ]
      },
      property: {
        propertyCode: null,
        propertyName: null,
        propertyType: null,
        propertyUnit: null,
        data: {
          xAxis: [],
          series: []
        }
      },
      pickerOptions: {
        shortcuts: [{
          text: '最近半小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 1800 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近一小时',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000)
            picker.$emit('pick', [start, end])
          }
        }, {
          text: '最近一天',
          onClick(picker) {
            const end = new Date()
            const start = new Date()
            start.setTime(start.getTime() - 3600 * 1000 * 24)
            picker.$emit('pick', [start, end])
          }
        }],
        disabledDate(time) {
          return time.getTime() > new Date(moment().endOf('day').valueOf())
        }
      },
      tableDataPaged: [],
      rules: {
        deviceType: [
          { required: true, message: '', trigger: 'blur' }
        ],
        deviceInstance: [
          { required: true, message: '', trigger: 'blur' }
        ],
        dataMode: [
          { required: true, message: '', trigger: 'blur' }
        ],
        time: [
          { required: true, message: '', trigger: 'blur' }
        ]
      },
      functionList: [],
      fft: {
        data: {
          xAxis: [],
          series: []
        }
      },
      sampling: {
        samplingRate: null,
        count: null,
        samplingPeriod: null
      },
      isSupported: false,
      activeFunction: null,
      functionChartData: [],
      functionChartDetail: {
        amplitude: null,
        frequency: null,
        phase: null,
        cycle: null
      },
      samplingList: []
    }
  },
  watch: {
    activeProperty(newVal) {
      if (newVal) {
        const property = this.propertyList.find(v => v.propertyCode === newVal)
        if (property) {
          const { propertyCode, propertyName, propertyType, propertyUnit } = property
          this.property = {
            propertyCode,
            propertyName,
            propertyUnit,
            propertyType,
            data: {
              xAxis: [],
              series: []
            }
          }
        }
      }
    },
    activeFunction: {
      immediate: true,
      handler: function(val) {
        this.functionChartData = this.getFuncChartData(val)
      }
    },
    form: {
      deep: true,
      handler: function() {
        this.$refs.form.clearValidate()
      }
    }
  },
  created() {
    const { deviceTypeId, deviceInstanceId } = this.$route.query
    this.init(deviceTypeId, deviceInstanceId)
  },
  methods: {
    async init(deviceTypeId, deviceInstanceId) {
      // 获取所有设备类型
      const deviceTypeList = await getAllDeviceModel()
      this.deviceTypeList = deviceTypeList.data
      this.form.deviceType = deviceTypeId || (this.deviceTypeList.length ? this.deviceTypeList[0].id : null)
      // 获取该设备类型下的设备实例
      const deviceInstanceList = await getAllInstanceByDeviceTypeId({ deviceTypeId: this.form.deviceType })
      this.deviceInstanceList = deviceInstanceList.data
      this.form.deviceInstance = deviceInstanceId || (this.deviceInstanceList.length ? this.deviceInstanceList[0].id : null)
      // 根据设备类型 ID 获取关联数据模型
      const dataModelList = await getDataModelByDeviceTypeId({ id: this.form.deviceType })
      this.dataModelList = dataModelList.data
      if (this.dataModelList.length) {
        this.form.dataMode = this.dataModelList[0].id
        this.dataModelList[0].propertyList.forEach(v => {
          if (v.propertyCode !== 'sampling_rate') {
            this.propertyList.push(v)
          }
        })
        this.samplingList = await getDataPreview({ modelId: this.form.dataMode, deviceId: this.form.deviceInstance })
        this.form.time = this.samplingList.length ? this.samplingList[0].time : null
        this.activeProperty = this.propertyList.length ? this.propertyList[0].propertyCode : null
        // 判断该模型是否支持频域分析,不支持则不获取数据
        if (this.isFrequency(this.dataModelList[0].propertyList)) {
          // 查询时域数据
          await this.queryData()
        }
      }
      return {}
    },
    isFrequency(propertyList = []) {
      const sampling = propertyList.find(v => v.propertyCode === 'sampling_rate')
      return sampling !== undefined
    },
    getChartData(propertyCode) {
      return this.tableData.map(v => {
        return {
          time: v.time,
          value: v[propertyCode]
        }
      })
    },
    queryData() {
      this.$refs.form.validate()
        .then(_ => {
          const index = this.dataModelList.findIndex(i => i.id === this.form.dataMode)
          // this.propertyList = [...this.dataModelList[index].propertyList]
          this.propertyList = []
          this.dataModelList[index].propertyList.forEach(v => {
            if (v.propertyCode !== 'sampling_rate') {
              this.propertyList.push(v)
            }
          })
          if (!this.isFrequency(this.dataModelList[index].propertyList)) {
            this.isSupported = false
            throw new Error('不支持')
          } else {
            this.isSupported = true
          }
          if (this.propertyList.length) {
            this.activeProperty = this.propertyList[0].propertyCode
          }
          const { dataMode, deviceInstance } = this.form
          this.getPropertyDetail(dataMode, deviceInstance)
        })
        .then(_ => {
          return {
            time: this.form.time,
            modelId: this.form.dataMode,
            deviceId: this.form.deviceInstance,
            propertyCodeList: this.propertyList.map(v => v.propertyCode)
          }
        })
        .then(params => getTimeDomainData(params))
        .then(res => {
          this.tableData = res.data[this.activeProperty]
          // this.pageForm.total = this.tableData.length
          // this.pageTableData()
          function strip(num, precision = 12) {
            return +parseFloat(num.toPrecision(precision))
          }
          const xAxis = []
          for (let i = 0; i < 1; i += 0.0001) {
            xAxis.push(strip(i))
          }
          this.property.data = {
            xAxis: xAxis,
            series: res.data[this.activeProperty]
          }
          return {
            time: this.form.time,
            modelId: this.form.dataMode,
            deviceId: this.form.deviceInstance,
            propertyCode: this.activeProperty
          }
        })
        .then(params => this.getFFTData(params))
        .catch(_ => {})
    },
    onDeviceTypeChange(val) {
      this.form.deviceInstance = null
      this.form.dataMode = null
      this.getAllInstanceByDeviceTypeId(val)
      this.getDataModelByDeviceTypeId(val)
    },
    getAllInstanceByDeviceTypeId(val) {
      getAllInstanceByDeviceTypeId({ deviceTypeId: val })
        .then(res => {
          this.deviceInstanceList = res.data
          if (this.deviceInstanceList.length) {
            this.form.deviceInstance = this.deviceInstanceList[0].id
          }
        })
        .catch(_ => {})
    },
    getPropertyDetail(dataModelId, deviceId) {
      getPropertyDetail({ dataModelId, deviceId })
        .then(res => {
          const propertyList = res.data.propertyList.length ? res.data.propertyList : []
          const samplingRate = propertyList.find(v => v.propertyCode === 'sampling_rate')
          if (samplingRate) {
            this.sampling = {
              samplingRate: samplingRate.propertyValue,
              count: null,
              samplingPeriod: 1 / (samplingRate.propertyValue * 1000000) * 1000 * 1000
            }
          }
        })
        .catch(_ => {})
    },
    getDataPreview(modelId, deviceId) {
      getDataPreview({ modelId, deviceId })
        .then(res => {
          this.samplingList = res.data
          this.form.time = this.samplingList.length ? this.samplingList[0].time : null
        })
    },
    getDataModelByDeviceTypeId(id) {
      getDataModelByDeviceTypeId({ id })
        .then(res => {
          this.dataModelList = res.data
          if (this.dataModelList.length) {
            this.form.dataMode = this.dataModelList[0].id
            this.getDataPreview(this.form.dataMode, this.form.deviceInstance)
          }
        })
        .catch(_ => {})
    },
    getFrequencyDomainData() {},
    generateData(amplitude, frequency, phase) {
      const length = frequency.toString().split('.')[0].length
      let step = '1'
      for (let i = 0; i < length; i++) {
        step += '0'
      }
      step = 0.1 / parseInt(step)
      const data = []
      function strip(num, precision = 12) {
        return +parseFloat(num.toPrecision(precision))
      }
      for (let i = 0; i < 1; i += step) {
        data.push([strip(i), this.func(strip(i), amplitude, frequency, phase)])
      }
      console.log(amplitude, frequency, phase)
      return data
    },
    func(x, amplitude = 1, frequency = 1, phase = 0) {
      return amplitude * Math.cos(2 * Math.PI * frequency * x + phase * Math.PI)
    },
    getFuncChartData(activeFunction) {
      const func = this.functionList.find(v => v.id === activeFunction)
      if (func) {
        const { amplitude, frequency, phase } = func.func
        this.functionChartDetail = {
          amplitude,
          frequency,
          phase
        }
        return this.generateData(amplitude, frequency, phase)
      } else {
        return []
      }
    },
    getFFTData(params) {
      getFrequencyDomainData(params)
        .then(res => {
          const { chart, functionList } = res.data
          const xAxis = chart.xdata
          const series = chart.ydata
          this.fft.data = { xAxis, series }
          this.functionList = functionList.map((v, i) => {
            const { amplitude, frequency, phase } = v
            const phaseNumber = (parseFloat(phase) / Math.PI).toFixed(2)
            const name = frequency === '0.00' ? '直流信号' : `${amplitude}*sin(2*Pi*${frequency}+${phaseNumber}*Pi)`
            return {
              id: i.toString(),
              name: name,
              func: {
                amplitude: parseFloat(amplitude),
                frequency: parseFloat(frequency),
                phase: parseFloat(phaseNumber)
              },
              data: []
            }
          })
          this.activeFunction = this.functionList.length ? this.functionList[0].id : null
          this.functionChartData = this.getFuncChartData(this.activeFunction)
        })
    },
    onDataZoom(params) {
      const { start, end } = params.val
      const action = {
        type: 'dataZoom',
        start,
        end
      }
      const ref = params.type === 'timeDomainLine' ? 'functionLine' : 'timeDomainLine'
      this.$refs[ref].dispatch(action)
    }
  }
}
</script>

<style scoped>

</style>
