<template>
  <BaseDialog
    width="450px"
    v-bind="$attrs"
    v-on="listeners"
    @submit="onSubmit"
    @open="onOpen"
    @closed="onClosed"
    top="8vh"
  >
    <el-form class="form" ref="form" v-bind="{ labelWidth: '10em', size: 'medium' }" :model="formData" :rules="rules">
      <el-form-item
        v-for="{ name, label, type, disabled, on = {}, options, ...rest } of formItems"
        :key="name"
        :label="label"
        :prop="name"
      >
        <el-time-picker v-if="type === 'timePicker'" v-model="formData[name]" v-bind="rest" v-on="on" />
        <el-select
          v-else-if="type === 'select'"
          v-model="formData[name]"
          :placeholder="`请选择${label}`"
          clearable
          v-bind="rest"
          v-on="on"
          style="width:100%"
        >
          <el-option v-for="item of options" :key="item.value" :value="item.value" :label="item.label" />
        </el-select>
        <el-switch v-else-if="type === 'switch'" v-model="formData[name]" v-bind="rest" v-on="on" />
        <el-input-number
          v-else-if="type === 'number'"
          v-model="formData[name]"
          controls-position="right"
          :placeholder="`请输入${label}`"
          v-bind="rest"
          v-on="on"
        />
        <el-checkbox v-else-if="type === 'checkbox'" v-model="formData[name]" v-bind="rest" v-on="on">
          {{ label }}
        </el-checkbox>
        <el-input
          v-else
          v-model="formData[name]"
          :placeholder="`请输入${label}`"
          :type="type || 'text'"
          :disabled="disabled"
          clearable
          v-bind="rest"
          v-on="on"
        />
      </el-form-item>
    </el-form>
  </BaseDialog>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import BaseDialog from '@/components/BaseDialog/index.vue'
import { ElForm } from 'element-ui/types/form'
import { IStandardParam, IDeviceTypeParam } from '../api/common'
import moment from 'moment'
import { deviceTypeParamPage } from '../api/deviceType'
import { IDictionary } from '@/api/common'
import { getDefalutNumberProp } from '@/utils/constant'

const format = 'HH:mm'

interface IFormData extends Partial<IStandardParam> {
  unit?: string
  range?: string
  timeRange?: (string | Date)[]
}

const getDefaultFormData = (): IFormData => ({
  isstart: 1,
  istidings: 1,
  timeRange: [moment('00:00', format).toDate(), moment('23:59', format).toDate()]
})

const getTime = (time: string | Date) => moment(time, format).format(format)

@Component({ name: 'ParamForm', components: { BaseDialog } })
export default class ParamForm extends Vue {
  @Prop({ type: Object, default: () => ({}) }) data!: IStandardParam
  @Prop({ type: Array, default: () => [] }) levels!: IDictionary[]
  @Prop({ type: [String, Number], default: '' }) typeId!: number

  $refs!: { form: ElForm }
  $listeners: { submit?: Function; open?: Function; closed?: Function }
  fetchingTypePrams = false

  get listeners() {
    const { submit, open, closed, ...rest } = this.$listeners
    return rest
  }

  formData: IFormData = getDefaultFormData()

  typeParams: IDeviceTypeParam[] = []

  rules = {
    targetId: [{ required: true, message: '请选择参数名称', trigger: 'change' }],
    lowerLimit: [{ required: true, message: '下限不能为空', trigger: 'blur' }],
    upperLimit: [{ required: true, message: '上限不能为空', trigger: 'blur' }],
    warningLevel: [{ required: true, message: '请选择报警级别', trigger: 'change' }]
  }

  get formItems() {
    return [
      {
        label: '参数名称',
        name: 'targetId',
        type: 'select',
        size: 'small',
        options: this.typeParams.map(({ id: value, targetName: label }) => ({ value, label })),
        on: { change: this.onTypeParamChange },
        loading: this.fetchingTypePrams,
        disabled: !!this.data.id
      },
      {
        label: '单位',
        name: 'targetUnit',
        required: false,
        disabled: true,
        size: 'small'
      },
      {
        label: '下限',
        name: 'lowerLimit',
        type: 'number',
        ...getDefalutNumberProp(),
        min: undefined,
        controls: false,
        precision: 2
      },
      {
        label: '下限预警容差',
        name: 'lowTolerance',
        type: 'number',
        required: false,
        ...getDefalutNumberProp(),
        controls: false,
        precision: 2,
        on: { change: () => this.onWarningChange('upTolerance') }
      },
      {
        label: '上限',
        name: 'upperLimit',
        type: 'number',
        ...getDefalutNumberProp(),
        controls: false,
        precision: 2
      },
      {
        label: '上限预警容差',
        name: 'upTolerance',
        type: 'number',
        required: false,
        ...getDefalutNumberProp(),
        controls: false,
        precision: 2,
        on: { change: () => this.onWarningChange('lowTolerance') }
      },
      {
        label: '报警级别',
        name: 'warningLevel',
        type: 'select',
        options: this.levels.map(({ id: value, notes: label }) => ({ value, label })),
        on: {
          change: this.onLevelChange
        }
      },
      {
        label: '有效时间',
        name: 'timeRange',
        type: 'timePicker',
        size: 'small',
        allowControl: true,
        isRange: true,
        style: 'width: 100%',
        clearable: true,
        startPlaceholder: '开始时间',
        endPlaceholder: '结束时间',
        valueFormat: format,
        format
      },
      {
        label: '是否启用',
        name: 'isstart',
        type: 'switch',
        activeValue: 1,
        inactiveValue: 0,
        size: 'small'
      },
      {
        label: '是否发送警报消息',
        name: 'istidings',
        type: 'switch',
        activeValue: 1,
        inactiveValue: 0,
        size: 'small'
      }
    ]
  }

  onWarningChange(key: 'upTolerance' | 'lowTolerance') {
    this.formData[key] = undefined
  }
  onLevelChange(id) {
    const { notes: warningName } = this.levels.find((item) => item.id === id) || {}
    this.formData.warningName = warningName
  }

  onTypeParamChange(id) {
    const { targetUnit } = this.typeParams.find((item) => item.id === id) || {}
    this.formData.targetUnit = targetUnit
  }

  onSubmit() {
    const form = this.$refs['form'] as any
    form.validate((valid) => {
      if (valid) {
        console.log(JSON.stringify(this.formData, null, 2))
        const {
          timeRange: [start, end],
          ...rest
        } = this.formData
        this.$emit('submit', { ...rest, biginTime: getTime(start), endTime: getTime(end) })
      }
    })
  }

  async onOpen() {
    if (!this.typeId) return
    this.fetchingTypePrams = true
    try {
      const {
        result: { records }
      } = await deviceTypeParamPage({ typeId: this.typeId, current: 1, size: 9999 })
      this.typeParams = records || []
    } catch (error) {
      console.log(error)
    }
    this.fetchingTypePrams = false
  }
  onClosed() {
    this.typeParams = []
    this.$emit('closed')
  }

  @Watch('data', { immediate: true })
  setDefaultData(val: IStandardParam) {
    const {
      biginTime: start,
      endTime: end,
      lowerLimit,
      lowTolerance,
      upperLimit,
      upTolerance,
      warningLevel,
      warningName,
      ...rest
    } = val
    this.formData = val.id
      ? {
          ...rest,
          warningLevel,
          warningName,
          lowerLimit: lowerLimit === null ? undefined : lowerLimit,
          lowTolerance: lowTolerance === null ? undefined : lowTolerance,
          upperLimit: upperLimit === null ? undefined : upperLimit,
          upTolerance: upTolerance === null ? undefined : upTolerance,
          timeRange: [
            start ? moment(start, format).toDate() : undefined,
            end ? moment(end, format).toDate() : undefined
          ]
        }
      : getDefaultFormData()
    if (!warningName && warningLevel) this.onLevelChange(warningLevel)
  }
}
</script>
<style lang="scss" scoped>
.form {
  >>> .el-input-number {
    width: 100%;
    .el-input__inner {
      text-align: left;
    }
  }
}
</style>
