<template>
  <div class="ta-table-edit" :class="{'table-edit': !record.editable && type != 'rowEdit', 'pd-r6': editable}">
    <template v-if="(editable || record.editable) && type != 'rowEdit'">
      <ta-form-item
        v-if="editForm"
        :field-decorator-id="tableTdDate.formId"
        :field-decorator-options="{ rules: rules, initialValue: tableTdDate.initialValue, valuePropName: type == 'switch' ? 'checked' : 'value'}"
        :wrapper-col="{ span: 24 }"
      >
        <ta-select v-if="type == 'select'" :ref="type" class="edit-form" :mode="multiple ? 'multiple':'default'" :placeholder="placeholder" @keyup.enter.native="cellSave">
          <ta-select-option v-for="item in option" :key="item.value" :value="item.value" :disabled="item.disabled">
            {{ item.label }}
          </ta-select-option>
        </ta-select>
        <ta-cascader v-else-if="type == 'cascader'" :ref="type" :options="option" class="edit-form" :placeholder="placeholder" />
        <ta-tree-select v-else-if="type == 'treeSelect'" :ref="type" :tree-data="option" :multiple="multiple" class="edit-form" :placeholder="placeholder" />
        <component :is="'ta-' + type" v-else-if="type.indexOf('Picker') != -1" :ref="type" class="edit-form" :placeholder="type != 'rangePicker' ? placeholder : [placeholder, placeholder]" @change="(dates, dateStrings) => dateChange(dates, dateStrings, tableTdDate.formId, type)" />
        <component :is="'ta-' + type" v-else-if="type.indexOf('inputNumber') != -1" :ref="type" class="edit-form" :placeholder="placeholder" :asAmount="asAmount" :amountPre="amountPre" />
        <component :is="'ta-' + type" v-else :ref="type" :class="{'edit-form': type != 'switch'}" :placeholder="placeholder"/>
      </ta-form-item>
      <template v-else>
        <ta-select v-if="type == 'select'" :ref="type" v-model="tempValue" class="edit-form" :mode="multiple ? 'multiple':'default'" :placeholder="placeholder" @keyup.enter.native="cellSave" @change="rowChange">
          <ta-select-option v-for="item in option" :key="item.value" :value="item.value" :disabled="item.disabled">
            {{ item.label }}
          </ta-select-option>
        </ta-select>
        <ta-cascader v-else-if="type == 'cascader'" :ref="type" v-model="tempValue" :options="option" class="edit-form" :placeholder="placeholder" @change="rowChange" />
        <ta-tree-select v-else-if="type == 'treeSelect'" :ref="type" v-model="tempValue" :tree-data="option" :multiple="multiple" class="edit-form" :placeholder="placeholder" @change="rowChange" />
        <component :is="'ta-' + type" v-else-if="type.indexOf('Picker') != -1" :ref="type" v-model="tempValue" class="edit-form" :placeholder="type != 'rangePicker' ? placeholder : [placeholder, placeholder]" @change="(dates, dateStrings) => dateChange(dates, dateStrings, tableTdDate.formId, type)" />
        <component :is="'ta-' + type" v-else-if="type.indexOf('inputNumber') != -1" :ref="type" v-model="tempValue" class="edit-form" :placeholder="placeholder" :asAmount="asAmount" :amountPre="amountPre" @change="rowChange" />
        <component :is="'ta-' + type" v-else :ref="type" v-model="tempValue" :class="{'edit-form': type != 'switch'}" :placeholder="placeholder" @change="rowChange" />
      </template>
    </template>

    <ta-rate v-if="!(editable || record.editable) && type == 'rate'" v-model="tableTdDate.initialValue" style="line-height: 31px;" :disabled="true" />
    <div v-if="!(editable || record.editable) && type != 'rate'" :class="{overflow: tableTdDate.overflow}" :style="tableTdDate.overflowWidth">
      <ta-tooltip v-if="tableTdDate.overflow" placement="topLeft" :title="getSpan">
        {{ getSpan }}
      </ta-tooltip>
      <span v-else>{{ getSpan }}</span>
    </div>
    <div v-if="type == 'rowEdit'">
      <div v-if="!record.editable">
        <a @click="tableChange(true)">修改</a>
        <ta-divider type="vertical" />
        <ta-popconfirm title="确认删除该条数据？" ok-text="确认" cancel-text="取消" @confirm="rowDelete">
          <a>删除</a>
        </ta-popconfirm>
      </div>
      <div v-else>
        <a @click="rowSave">保存</a>
        <ta-divider type="vertical" />
        <a @click="tableChange(false)">取消</a>
      </div>
    </div>
    <ta-icon v-if="!rowEditable && type != 'rowEdit'" :type="editable ? 'check' : 'edit'" class="edit-cell-icon" :class="{'edit-hover': !editable, 'check-icon': editable}" @click="cellSave" />
    <ta-icon v-if="editable" type="close" class="edit-cell-icon" :class="{'edit-hover': !editable}" @click="editable = false" />
  </div>
</template>
<script>
import moment from 'moment'
import {mapGetters, mapActions} from 'vuex'
import cloneDeep from 'lodash.clonedeep'
export default {
  name: 'TaTableEdit',
  props: {
    type: {
      type: String,
      default: 'input',
    },
    dataSource: {
      type: Array,
    },
    rowKey: {
      type: String,
      default: 'key',
    },
    option: {
      type: Array,
    },
    rowEditable: {
      type: Boolean,
      default: false,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    trueText: {
      type: String,
      default: '是',
    },
    falseText: {
      type: String,
      default: '否',
    },
    placeholder: {
      type: String,
      default: '',
    },
    rules: {
      type: Array,
      default: () => [],
    },
    beforeChange: {
      type: Function,
    },
    editForm: {
      type: Object,
      default: () => {},
    },
    asAmount: {
      type: Boolean,
      default: false,
    },
    amountPre: {
      type: String,
      default: '￥',
    },
  },
  data () {
    return {
      editable: false,
      tempValue: null,
    }
  },
  computed: {
    ...mapGetters('tableEdit', ['getRecord']),
    tableTd () {
      /* 寻找父级td */
      return this.getTableTd()
    },
    /* td的数据 */
    tableTdDate () {
      const {column, record, index} = this.tableTd
      let result = {
        formId: column.dataIndex + '?' + index,
        columnKey: column.dataIndex,
        record: record,
        recordIndex: index,
        overflow: column.overflowTooltip || false,
      }
      result.initialValue = this.dateFormat(record[result.columnKey])
      if (result.overflow) {
        let columnWidth = column.width
        let width = columnWidth && columnWidth.toString().indexOf('%') == -1 ? parseInt(columnWidth) - 62 + 'px' : `100%`
        result.overflowWidth = {width: width}
      }
      return result
    },
    record () {
      return this.tableTdDate.record
    },
    getSpan () {
      const {type, trueText, falseText, editForm, asAmount, amountPre} = this
      const {record, columnKey} = this.tableTdDate
      let initValue = record[columnKey], span = initValue
      Object.assign(this.tableTdDate, {initialValue: this.dateFormat(initValue), tempValue: this.tempValue})
      switch (type) {
        case 'select': span = this.optionLabel(initValue).join('、'); break
        case 'rangePicker': span = initValue && initValue.length ? initValue[0] + '~' + initValue[1] : ''; break
        case 'weekPicker': span = initValue ? initValue + '周' : ''; break
        case 'switch': span = initValue ? trueText : falseText; break
        case 'cascader': span = this.optionLabel(initValue).join('/'); break
        case 'treeSelect': span = this.optionLabel(initValue).join('、'); break
        case 'inputNumber': span = asAmount ? amountPre + span.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : span; break
        default: break
      }
      return span
    },
  },
  watch: {
    record (val) {
      if (val.editable) {
        this.tempValue = this.tableTdDate.initialValue
      }
    },
  },
  methods: {
    moment,
    ...mapActions('tableEdit', ['setRecord', 'resetRecord']),
    /* 获取表格td */
    getTableTd (parent = this.$parent) {
      let result = {}
      if (parent.component && parent.component == 'td') {
        result = parent
      } else {
        result = this.getTableTd(parent.$parent)
      }
      return result
    },
    /* 时间从空值变化时保存format */
    dateChange (dates, dateStrings, formId, type) {
      const {record, columnKey} = this.tableTdDate
      if (this.editForm) {
        if (type == 'rangePicker') {
          if (dates.length && !dates[0]._f) {
            this._fnSetDate(formId, dateStrings)
          }
        } else {
          if (dates && !dates._f) {
            this._fnSetDate(formId, dateStrings)
          }
        }
      } else {
        if (type == 'weekPicker') {
          dateStrings = dateStrings.indexOf('周') == -1 ? dateStrings.substr(0, dateStrings.length - 2) : dateStrings.substr(0, dateStrings.length - 1)
        }
        if (record.editable) {
          let temp = {}
          temp[columnKey] = dateStrings
          this.setRecord(temp)
        }
      }
    },
    _fnSetDate (formId, dateStrings) {
      let param = {}
      param[formId] = this.dateFormat(dateStrings)
      this.$nextTick(() => {
        this.editForm.setFieldsValue(param)
      })
    },
    /* 时间转换 */
    dateFormat (data, toString) {
      let result = data
      if (this.type.indexOf('Picker') != -1) {
        if (data) {
          switch (this.type) {
            case 'datePicker': result = toString ? data.format('YYYY-MM-DD') : moment(data, 'YYYY-MM-DD'); break
            case 'monthPicker': result = toString ? data.format('YYYY-MM') : moment(data, 'YYYY-MM'); break
            case 'rangePicker': result = data && data.length && data[0] && data[1] ? (toString ? [data[0].format('YYYY-MM-DD'), data[1].format('YYYY-MM-DD')] : [moment(data[0], 'YYYY-MM-DD'), moment(data[1], 'YYYY-MM-DD')]) : null; break
            case 'weekPicker': result = toString ? data.format('YYYY-ww') : moment(data, 'YYYY-ww'); break
            default: break
          }
        } else {
          result = null
        }
      }
      return result
    },
    /* 下拉类型显示文字 */
    optionLabel (text) {
      let list = this.option || [], result = []
      if (text != undefined) {
        if (this.type == 'select') {
          if (this.multiple) { // 多选
            text.forEach((item) => {
              result = result.concat(this.getSelectLabel(item, list))
            })
          } else { // 单选
            result = this.getSelectLabel(text, list)
          }
        } else if (this.type == 'cascader' && text.length) {
          result = this.getCascaderLabel(text, list, 0)
        } else if (this.type == 'treeSelect') {
          if (this.multiple) { // 多选
            text.forEach((item) => {
              result = result.concat(this.getTreeSelectLabel(item, list))
            })
          } else { // 单选
            result = this.getTreeSelectLabel(text, list)
          }
        }
      }
      return result
    },
    getSelectLabel (text, list) {
      let result = []
      for (let i = 0; i < list.length; i++) {
        if (text == list[i].value) { result.push(list[i].label); break }
      }
      return result
    },
    getCascaderLabel (text, list, index) {
      let result = []
      for (let i = 0; i < list.length; i++) {
        if (text[index] == list[i].value) {
          result.push(list[i].label)
          if (index + 1 < text.length && list[i].children) {
            result = result.concat(this.getCascaderLabel(text, list[i].children, index + 1))
          }
          break
        }
      }
      return result
    },
    getTreeSelectLabel (text, list) {
      let result = []
      for (let i = 0; i < list.length; i++) {
        if (list[i].value == text) {
          result.push(list[i].label)
          return result
        }
        if (list[i].children) {
          result = result.concat(this.getTreeSelectLabel(text, list[i].children))
        }
      }
      return result
    },
    // 行编辑editable状态修改
    tableChange (editable) {
      const newData = [...this.dataSource]
      const oldEdit = newData.filter(item => item.editable === true)[0]
      const target = newData.filter(item => this.record[this.rowKey] === item[this.rowKey])[0]
      if (oldEdit && target && oldEdit[this.rowKey] != target[this.rowKey]) {
        delete oldEdit.editable
      }
      if (target) {
        if (editable) {
          target.editable = true
        } else {
          delete target.editable
        }
      }
      if (!this.editForm) {
        this.resetRecord()
      }
      this.$emit('tableChange', cloneDeep(newData))
    },
    /* 单元格编辑保存 */
    cellSave () {
      if (this.editable) {
        const {record, columnKey, formId} = this.tableTdDate
        if (this.editForm) {
          this.editForm.validateFields([formId], (error, values) => {
            if (!error) {
              this._cellSaveHandle(this.dateFormat(values[formId], true), record, columnKey)
            }
          })
        } else {
          this._cellSaveHandle(this.dateFormat(this.tempValue, true), record, columnKey)
        }
      } else {
        this.editable = true
        this.tempValue = this.tableTdDate.initialValue
        this.$nextTick(() => {
          this.$refs[this.type].focus()
        })
      }
    },
    /* 单元格验证、不验证的保存 */
    _cellSaveHandle (newData, record, columnKey) {
      let changeData = {
        newData: newData,
        record: record,
        columnKey: columnKey,
      }
      if (this.beforeChange) {
        this.beforeChange(changeData, (error) => {
          if (error) {
            this.$message.error(error)
          } else {
            this.editable = false
            if (this.type == 'rate') {
              Object.assign(this.tableTdDate, {initialValue: newData})
            }
            this.$emit('change', changeData)
          }
        })
      } else {
        this.editable = false
        if (this.type == 'rate') {
          Object.assign(this.tableTdDate, {initialValue: newData})
        }
        this.$emit('change', changeData)
      }
    },
    /* 行编辑保存 */
    rowSave () {
      if (this.editForm) {
        this.editForm.validateFields((error, values) => {
          if (!error) {
            let result = {}
            Object.keys(values).forEach((item) => {
              let value = values[item], key = item.substr(0, item.indexOf('?'))
              if (value && (value._d || (value[0] && value[0]._d))) {
                let format = value._f || value[0]._f
                result[key] = value[0] && value[0]._d ? [value[0].format(format), value[1].format(format)] : value.format(format)
              } else {
                result[key] = cloneDeep(value)
              }
            })
            this._rowSaveHandle(result, this.record, this.record[this.rowKey])
          }
        })
      } else {
        let result = Object.assign({}, this.record, this.getRecord)
        this._rowSaveHandle(result, this.record, this.record[this.rowKey])
      }
    },
    /* 单元行验证、不验证的保存 */
    _rowSaveHandle (newData, record, rowKey) {
      let changeData = {
        newData: newData,
        record: record,
        rowKey: rowKey,
      }
      if (this.beforeChange) {
        this.beforeChange(changeData, (error) => {
          if (error) {
            this.$message.error(error)
          } else {
            this.$emit('change', changeData)
            this.tableChange(false)
          }
        })
      } else {
        this.$emit('change', changeData)
        this.tableChange(false)
      }
    },
    /* 没有form时行编辑保存每个单项 */
    rowChange () {
      const {record, columnKey} = this.tableTdDate
      if (!this.editForm && record.editable) {
        let temp = {}
        temp[columnKey] = this.tempValue
        this.setRecord(temp)
      }
    },
    /* 行编辑删除 */
    rowDelete () {
      this.$emit('rowDelete', this.record[this.rowKey])
    },
  },
}
</script>
