<template>
  <d2-container>
    <d2-crud
      ref="d2Crud"
      :columns="columns"
      :data="data"
      :rowHandle="rowHandle"
      add-title="新增节点"
      edit-title="修改节点信息"
      :add-template="addTemplate"
      :edit-template="editTemplate"
      :form-options="formOptions"
      :add-rules="addRules"
      @row-add="handleRowAdd"
      @row-edit="handleRowEdit"
      @row-remove="handleRowRemove"
      @dialog-cancel="handleDialogCancel">
      <el-button slot="header" style="margin-bottom: 5px" @click="addRow">新增</el-button>
      <el-button slot="header" style="margin-bottom: 5px">
        <el-upload
          class="upload-demo"
          ref="upload"
          action=""
          :before-upload="handleBatchRowAdd">
          批量导入
          <el-popover
            placement="right"
            width="688"
            trigger="hover">
              <el-card class="box-card">
                <d2-markdown :source="tips"/>
              </el-card>
            <el-button slot="reference" style="float: right"><d2-icon name="question-circle" /></el-button>
          </el-popover>
        </el-upload>
      </el-button>
    </d2-crud>
  </d2-container>
</template>

<script>
import tips from './tips.md'
import jschardet from 'jschardet'
import { assign, each, pick, pickBy, startsWith, includes, every } from 'lodash'

export default {
  data () {
    return {
      tips,
      columns: [
        {
          title: '序号',
          key: 'id'
        },
        {
          title: '节点编码',
          key: 'code'
        },
        {
          title: '节点名称',
          key: 'name'
        },
        {
          title: '类型',
          key: 'type'
        },
        {
          title: '数据类别',
          key: 'category'
        },
        {
          title: '工序单元',
          key: 'working_subclass'
        },
        {
          title: '创建时间',
          key: 'create_date'
        },
        {
          title: '备注',
          key: 'note'
        }
      ],
      data: [],
      rowHandle: {
        minWidth: '200',
        edit: {
          icon: 'el-icon-edit',
          text: '编辑',
          size: 'small',
          show (index, row) {
            if (row.showEditButton) {
              return true
            }
            return false
          }
        },
        remove: {
          icon: 'el-icon-delete',
          size: 'small',
          fixed: 'right',
          confirm: true,
          show (index, row) {
            if (row.showRemoveButton) {
              return true
            }
            return false
          }
        }
      },
      addTemplate: {
        code: {
          title: '节点编码'
        },
        name: {
          title: '节点名称'
        },
        type: {
          title: '类型',
          value: '',
          component: {
            name: 'el-select',
            options: [
              {
                value: 'string',
                label: 'string (字符串)'
              },
              {
                value: 'int',
                label: 'int (整数)'
              },
              {
                value: 'float',
                label: 'float (浮点数)'
              },
              {
                value: 'bool',
                label: 'bool (逻辑值)'
              }
            ],
            span: 12
          }
        },
        category: {
          title: '数据类别',
          value: '',
          component: {
            name: 'el-select',
            options: [
              {
                value: 'DEVICE_STATUS',
                label: '设备状态'
              },
              {
                value: 'ITEM_ID_ITEM',
                label: '编号'
              },
              {
                value: 'DEVICE_DATA',
                label: '运行数据'
              },
              {
                value: 'PROCESS_DATA',
                label: '过程数据'
              },
              {
                value: 'RESULT_DATA',
                label: '结果数据'
              },
              {
                value: 'STATISTICAL_DATA',
                label: '统计数据'
              }
            ],
            span: 12
          }
        },
        working_subclass: {
          title: '工序单元'
        },
        note: {
          title: '备注'
        }
      },
      editTemplate: {
        name: {
          title: '节点名称'
        },
        note: {
          title: '备注'
        }
      },
      formOptions: {
        labelWidth: '80px',
        labelPosition: 'left',
        saveLoading: false
      },
      addRules: {
        code: [{ required: true, type: 'string', message: '节点编码必须填写', trigger: 'blur' }],
        name: [{ required: true, type: 'string', message: '节点名称必须填写', trigger: 'blur' }],
        type: [{ required: true, message: '必须指定节点类型', trigger: 'blur' }],
        category: [{ required: true, message: '必须指定数据类别', trigger: 'blur' }],
        working_subclass: [{
          required: true,
          type: 'string',
          message: '工序单元必须填写',
          trigger: 'blur'
        }]
      }
    }
  },
  methods: {
    async getNodes () {
      try {
        const res = await this.$api.QUERY_NODES()
        this.data = each(res, (o) => (
          assign(o, {
            showEditButton: true,
            showRemoveButton: true
          })
        ))
      } catch (e) {
        console.log(e)
      }
    },
    // 普通的新增
    addRow () {
      this.$refs.d2Crud.showDialog({
        mode: 'add'
      })
    },
    async handleRowAdd (row, done) {
      this.formOptions.saveLoading = true
      try {
        await this.$api.ADD_NODE(assign(row, { action: 'add_node' }))
        this.$message({
          message: '添加成功',
          type: 'success'
        })
      } catch (e) {
        console.log(e)
      }
      this.getNodes()
      done()
      this.formOptions.saveLoading = false
    },
    readFile (file) {
      return new Promise((resolve) => {
        const reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = function (e) {
          resolve(e.target.result)
        }
      })
    },
    async importConfig (file) {
      try {
        const buffer = await this.readFile(file)
        const encoding = jschardet.detect(Buffer.from(buffer.split(';base64,')[1], 'base64')).encoding
        if (encoding !== 'UTF-8') {
          this.$message.error(`导入的配置文件必须为UTF-8编码，但当前文件为${encoding}编码`)
          throw new TypeError('文件编码错误')
        } else {
          this.$import.csv(file)
            .then(res => {
              each(res.data, (row) => {
                if (!includes(['string', 'int', 'float', 'bool'], row.type)) {
                  this.$message.error('type字段必须为string|int|float|bool中的一种！')
                  throw new TypeError('type字段设置错误')
                } else if (!every([row.code, row.name, row.working_subclass], Boolean)) {
                  this.$message.error('code/name/working_subclass字段不可以为空！')
                  throw new TypeError('缺少必填字段')
                } else {
                  this.$api.ADD_NODE(assign(row, { action: 'add_node' }))
                  this.getNodes()
                  this.$refs.upload.clearFiles()
                }
              })
            })
            .catch(e => {
              console.log(e)
            })
        }
      } catch (e) {
        console.log(e)
      }
    },
    handleBatchRowAdd (file) {
      this.importConfig(file)
      return false
    },
    async handleRowEdit ({ index, row }, done) {
      this.formOptions.saveLoading = true
      await this.$api.UPDATE_NODE(assign(pickBy(row, (v, k) => (!startsWith(k, 'show'))), { action: 'update_node' }))
      this.$message({
        message: '编辑成功',
        type: 'success'
      })
      done()
      this.formOptions.saveLoading = false
    },
    async handleRowRemove ({ index, row }, done) {
      await this.$api.REMOVE_NODE(assign(pick(row, ['code', 'working_subclass']), { action: 'remove_node' }))
      this.$message({
        message: '删除成功',
        type: 'success'
      })
      done()
    },
    handleDialogCancel (done) {
      this.$message({
        message: '用户放弃改动',
        type: 'warning'
      })
      done()
    }
  },
  mounted () {
    this.getNodes()
  }
}
</script>
