<template>
  <div>
    <vxe-grid ref="xGrid" v-bind="gridOptions" @page-change="pageChangeEvent" @current-change="currentChangeEvent" @cell-dblclick="cellDBLClickEvent">
      <template v-slot:toolbar_buttons>
        <template v-for="(item, idx) in gridOptions.toolbar.buttons">
          <vxe-button v-if="item.type === 'button'" :status="item.status" :key="idx" :icon="item.icon" @click="item.onclick" >{{item.name}}</vxe-button>
          <vxe-input v-else-if="item.type === 'input'" :key="idx" :placeholder="item.placeholder"></vxe-input>
          <vxe-button v-else :status="item.status" :key="idx" :icon="item.icon" @click="item.onclick">{{item.name}}</vxe-button>
        </template>
      </template>
    </vxe-grid>
    <vxe-modal
      v-model="showEdit"
      :title="selectRow ? '编辑&保存' : '新增&保存'"
      width="800"
      min-width="640"
      :loading="submitLoading"
      resize
      :destroy-on-close="destroyOnClose"
      @show="onShowModal"
      @close="() => this.$refs.xForm.toggleCollapse()"
    >
      <vxe-form ref="xForm"
        :data="formData"
        :items="formItems"
        :rules="formRules"
        title-align="right"
        title-width="100"
        @submit="submitEvent"
      >
        <template v-for="(item, idx) in formItems" >
          <vxe-form-item :title="item.title" :field="item.field" :key="idx" :span="item.span">
            <template v-slot="scope">
              <vxe-input v-model="formData[item.field]" v-if="item.itemRender.name === '$input'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></vxe-input>
              <tse-num-input v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tseNumInput'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-num-input>
              <tse-date-input v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tseDateInput'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-date-input>
              <tse-pattern-input v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tsePatternInput'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-pattern-input>
              <tse-code-input v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tseCodeInput'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-code-input>
              <tse-phone-input v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tsePhoneInput'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-phone-input>
              <vxe-select v-model="formData[item.field]" v-else-if="item.itemRender.name === '$select'" :key="idx" v-bind:options="item.itemRender.options" @input="$refs.xForm.updateStatus(scope)"></vxe-select>
              <tse-tree-select v-model="formData[item.field]" v-else-if="item.itemRender.name === 'tseTreeSelect'" :key="idx" v-bind="item.itemRender.props" @input="$refs.xForm.updateStatus(scope)"></tse-tree-select>
              <vxe-input v-model="formData[item.field]" v-else :key="idx" v-bind="item.itemRender.props"></vxe-input>
            </template>
          </vxe-form-item>
        </template>
        <vxe-form-item align="right" span="24">
          <tse-form-navigator ref='xFormNavigator' v-if="selectRow"/>
          <vxe-button @click="btnReloadHandle">刷新</vxe-button>
          <vxe-button type="submit" status="primary">保存</vxe-button>
          <vxe-button @click="showEdit=false" status="info">关闭</vxe-button>
        </vxe-form-item>
      </vxe-form>
    </vxe-modal>
  </div>
</template>
<script>
import create from '../utils/create'
import _ from 'lodash-uuid'
import { Grid } from 'vxe-table'

const formSearchButtons = {
  span: 24,
  align: 'center',
  collapseNode: true,
  itemRender: {
    name: '$buttons',
    children: [
      {
        props: {
          type: 'submit',
          content: '查询',
          status: 'primary'
        }
      },
      {
        props: {
          type: 'reset',
          content: '重置'
        }
      }
    ]
  }
}

const defaultOptions = {
  showEdit: false,
  selectRow: false,
  submitLoading: false,
  border: true,
  headerAlign: 'center',
  resizable: true,
  showHeaderOverflow: true,
  showOverflow: true,
  highlightHoverRow: true,
  highlightCurrentRow: true,
  keepSource: true,
  stripe: true,
  height: 600,
  id: _.uuid(),
  rowId: 'id',
  customConfig: {
    storage: true
  },
  sortConfig: {
    trigger: 'cell'
  },
  filterConfig: {
    remote: true
  },
  pagerConfig: {
    total: 0,
    currentPage: 1,
    align: 'right',
    pageSize: 10,
    pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000],
    layouts: ['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total'],
    perfect: true
  },
  formConfig: {
    titleWidth: 100,
    titleAlign: 'right'
  },
  toolbar: {
    custom: true,
    slots: {
      buttons: 'toolbar_buttons'
    },
    refresh: true,
    import: true,
    export: true,
    print: true,
    zoom: true
  },
  proxyConfig: {
    seq: true, // 启用动态序号代理
    sort: true, // 启用排序代理
    filter: true, // 启用筛选代理
    form: true // 启用表单代理
  },
  importConfig: {
    remote: true,
    types: ['xlsx'],
    modes: ['insert']
  },
  exportConfig: {
    remote: true,
    types: ['xlsx'],
    modes: ['current', 'selected', 'all']
  }
}

const methods = {}

Object.keys(Grid.methods).forEach(name => {
  methods[name] = function (...args) {
    return this.$refs.xGrid && this.$refs.xGrid[name](...args)
  }
})

let formData = {}
const submitRecords = { insertRecords: [], pendingRecords: [], removeRecords: [], updateRecords: [] }

export default create({
  name: 'table',
  components: {
    navigator
  },
  props: {
    ...Grid.props,
    options: {
      type: Object,
      default () {
        return {}
      }
    }
  },
  provide () {
    return {
      $xegrid: this
    }
  },
  data () {
    let formItems = []
    let formConfig = defaultOptions.formConfig
    formConfig.items = []
    _.forEach(this.options.columns, (obj, idx) => {
      if (obj.field) {
        formData[obj.field] = null
        let colFormConfig = obj.formConfig
        if (colFormConfig) {
          colFormConfig.field = obj.field
          colFormConfig.title = obj.title
          if (colFormConfig.inFilterForm) {
            colFormConfig.itemRender.props = Object.assign({}, colFormConfig.itemRender.props, { clearable: true })
            formConfig.items.push(colFormConfig)
          }
          formItems.push(colFormConfig)
        }
      }
    })
    formConfig.items.push(formSearchButtons)
    _.forEach(this.options.toolbar.buttons, item => {
      if (!item.onclick) {
        item.onclick = () => void (0)
      }
    })
    return {
      gridOptions: _.merge(defaultOptions, this.options, {
        formConfig: formConfig
      }),
      showEdit: this.showEdit,
      selectRow: null,
      submitLoading: this.submitLoading,
      formData: Object.assign({}, formData),
      formItems: formItems,
      formRules: Object.assign({}, this.options.formRules),
      destroyOnClose: true
    }
  },
  created () {
    this.formItems.forEach((item, idx) => {
      let rules = this.options.formRules[item.field] || []
      item.itemRender.required = rules.filter(rule => { return rule.required }).length > 0
      if (item.itemRender && ['tsePatternInput', 'tseCodeInput'].indexOf(item.itemRender.name) >= 0) {
        let validRule = {
          validator: ({ $form, rule }) => {
            return new Promise((resolve, reject) => {
              $form.clearValidate(item.field)
              let input = $form.$children[idx].$children[0]
              let inputValue = '' || input.$el.querySelector('input').value
              if (!input.isComplete()) {
                reject(new Error(item.title + ' 输入不完整'))
              } else if (rule.required && inputValue === '') {
                reject(new Error(item.title + ' 不能为空'))
              } else {
                resolve()
              }
            })
          }
        }
        if (rules.length > 0) {
          Object.assign(rules[0], validRule)
        } else {
          rules.push(validRule)
        }
        this.formRules[item.field] = rules
      }
    })
  },
  methods: {
    ...methods,
    currentChangeEvent ({ row }) {
      this.formData = row
      if (this.selectRow !== row) this.selectRow = row
    },
    onShowModal () {
      if (!this.selectRow) {
        this.$refs.xGrid.clearCurrentRow()
        this.formData = formData
      } else {
        this.formData = Object.assign({}, this.selectRow)
      }
      this.$refs.xForm.toggleCollapse()
    },
    submitEvent ({ row }) {
      this.submitLoading = true
      if (this.selectRow) {
        submitRecords.updateRecords.push(this.formData)
      } else {
        submitRecords.insertRecords.push(this.formData)
      }
      this.gridOptions.proxyConfig.ajax.save(submitRecords)
        .then(data => {
          Object.keys(submitRecords).forEach((key) => { submitRecords[key] = [] })
          if (this.selectRow) {
            Object.assign(this.selectRow, this.formData)
            this.$refs.xGrid.reloadRow(this.selectRow)
          } else {
            this.insert(this.formData)
            this.commitProxy('reload')
            this.$refs.xForm.$el.reset()
          }
          this.$XModal.message({ message: '提交成功', status: 'success' })
          this.submitLoading = false
          // this.showEdit = false
        })
        .catch((e) => {
          this.submitLoading = false
          // this.showEdit = false
          this.$XModal.message({ message: '提交失败', status: 'danger' })
        })
    },
    cellDBLClickEvent ({ row }) {
      this.formData = row
      this.showEdit = true
    },
    removeRow () {
      if (this.selectRow) {
        this.$XModal.confirm('您确定要删除该数据?').then(type => {
          if (type === 'confirm') {
            submitRecords.removeRecords.push(this.selectRow)
            this.gridOptions.proxyConfig.ajax.save(submitRecords)
              .then(data => {
                Object.keys(submitRecords).forEach((key) => { submitRecords[key] = [] })
                this.remove(this.selectRow)
                this.$XModal.message({ message: '删除成功', status: 'success' })
              })
              .catch(e => {
                this.$XModal.message({ message: '提交失败', status: 'danger' })
              })
          }
        })
      }
    },
    btnReloadHandle () {
      let selectRowData = Object.assign({}, formData, this.selectRow)
      for (let key in selectRowData) {
        selectRowData[key] = selectRowData[key] === '' ? null : selectRowData[key]
      }
      this.$set(this, 'formData', selectRowData)
    },
    pageChangeEvent ({ type, pageSize }) {
      if (type === 'size') {
        this.$refs.xFormNavigator && this.$refs.xFormNavigator.refresh()
      }
    }
  },
  mounted () {
    this.$nextTick(() => {
      let headerList = this.$refs.xGrid.$refs.xTable.$refs.tableHeader.$el.querySelectorAll('th.vxe-header--column')
      headerList.forEach((item) => {
        item.className = item.className.replace(/(col--right|col--left|col--center)/, 'col--' + this.gridOptions.headerAlign)
      })
    })
  }
})
</script>
<style>
.vxe-button--icon + .vxe-button--content,
.vxe-button--loading-icon + .vxe-button--content {
  margin-left: 0.3em;
  vertical-align: middle;
}
</style>
