<template>
  <div v-if="!tableHidden" class="ibps-table-wrapper">
    <van-collapse v-model="activeCollapseNames">
      <!--一对一-->
      <template v-if="isOne2One">
        <van-collapse-item
          :name="collapseNameKey+'0'"
          :is-link="false"
        >
          <template #title>
            <div class="van-cell table-cell ">
              <div class="van-cell__title">
                {{ field.label }}
              </div>
            </div>
          </template>
          <!--子表字段-->
          <ibps-dynamic-form-table-block
            v-for="(column,j) in columns"
            :ref="'formItem'"
            :key="j"
            :models.sync="dataModel[i]"
            :rights.sync="columnsRights"
            :form-data="formData"
            :row="i"
            :field="column"
            :desc-position="descPosition"
            :main-code="mainCode"
            :code="code"
            :mode="mode"
            :readonly-rights="readonlyRights"
            :params="params"
            @update-form-data="updateFormData"
          />
        </van-collapse-item>
      </template>
      <!--一对多-->
      <template v-else>
        <van-collapse-item
          v-for="(data,i) in dataModel"
          :key="i"
          :name="collapseNameKey+i"
          :test="collapseNameKey+i"
          :is-link="isLink"
        >
          <template #title>
            <div class="van-cell table-cell">
              <div class="van-cell__title">
                <i v-if="required" class="van-cell--required" /><van-tag v-if="dataModel.length !== 1" round type="primary">{{ i+1 }}</van-tag> {{ field.label }}
              </div>
              <div class="van-cell__value" @click.stop="stopClick">
                <!-- <template v-for="(button,b) in toolbarButtons ">
                  <template v-if="!(button.key === 'remove' && mode==='block' && dataModel.length===1) "> -->
                <template v-for="(button,b) in (getShowBtn().length<=num?getShowBtn():getShowBtn().slice(0,num-1)) ">
                  <template>
                    <!-- 工具栏-->
                    <van-tag
                      :key="i+'-'+b"
                      size="medium"
                      class="ibps-mr-5"
                      :color="button.type | optionsFilter(colorOptions,'color','type')"
                      :text-color="button.type | optionsFilter(colorOptions,'textColor','type')"
                      @click="handleActionEvent(button,i)"
                    >
                      {{ button.label }}</van-tag>
                    <!-- <van-button
                      :key="b"
                      :type="button.type"
                      size="mini"
                      plain
                      class="ibps-mr-5"
                      @click.stop="handleActionEvent(button,i)"
                    >
                      {{ button.label }}
                    </van-button> -->
                  </template>
                </template>
                <template v-if="getShowBtn().length >num">
                  <template>
                    <van-tag
                      :key="'tag'+i"
                      size="medium"
                      class="ibps-mr-5"
                      :color="'danger' | optionsFilter(colorOptions,'color','type')"
                      :text-color="'danger' | optionsFilter(colorOptions,'textColor','type')"
                      @click="toggleBtn(i)"
                    >
                      更多<van-icon :name="toggle!==field.id+''+i ? 'arrow-down': 'arrow-up'" /></van-tag>
                  </template>
                </template>
                <!-- todo -->
                <div v-if="getShowBtn().length >num && toggle===field.id+''+i" v-clickoutside="outFn">
                  <div class="btn-pop-top" />
                  <div class="btn-pop">
                    <div
                      v-for="(button,b) in getShowBtn().slice(num-1) "
                      :key="button.key+b"
                      class="btn-pop-text"
                      @click.stop="handleActionEvent(button,i)"
                    >
                      {{ button.label }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <template #icon>
            <div class="ibps-pl-15 table-cell-icon"><van-icon :name="activeCollapseNames.includes(collapseNameKey+i) ? 'arrow-down': 'arrow-up'" /></div>
          </template>
          <!--子表字段-->
          <ibps-dynamic-form-table-block
            v-for="(column,j) in columns"
            :ref="'formItem'"
            :key="i+j"
            :models.sync="dataModel[i]"
            :rights.sync="columnsRights"
            :form-data="formData"
            :row="i"
            :field="column"
            :desc-position="descPosition"
            :main-code="mainCode"
            :code="code"
            :mode="mode"
            :readonly-rights="readonlyRights"
            :params="params"
            @update-form-data="updateFormData"
          />
        </van-collapse-item>
        <template v-if="dataModel.length === 0">
          <van-field
            ref="input"
            v-model="inputValue"
            :required="required"
            :rules="tableReadonly?null:rules"
            class="table-field"
          >
            <template #input>
              <van-collapse-item
                :name="collapseNameKey+'0'"
                :test="collapseNameKey+'0'"
                style="width: 100%;"
                :is-link="false"
              >
                <template #title>
                  <div class="van-cell table-cell">
                    <div class="van-cell__title">
                      <i v-if="required" class="van-cell--required" /> {{ field.label }}
                    </div>
                    <div class="van-cell__value">

                      <!-- 工具栏-->
                      <!-- <template
                        v-for="(button,j) in toolbarButtons"
                      >
                        <van-button
                          v-if="button.key !== 'remove'"
                          :key="j"
                          :type="button.type"
                          size="mini"
                          plain
                          class="ibps-mr-5"
                          @click.stop="handleActionEvent(button)"
                        >
                          {{ button.label }}
                        </van-button>
                      </template> -->

                      <template v-for="(button,j) in (getShowBtnByRemove().length<=num?getShowBtnByRemove():getShowBtnByRemove().slice(0,num-1)) ">
                        <van-tag
                          :key="j"
                          size="medium"
                          class="ibps-mr-5"
                          :color="button.type | optionsFilter(colorOptions,'color','type')"
                          :text-color="button.type | optionsFilter(colorOptions,'textColor','type')"
                          @click.stop="handleActionEvent(button)"
                        >
                          {{ button.label }}</van-tag>
                      </template>
                      <template v-if="getShowBtnByRemove().length >num">
                        <template>
                          <van-tag
                            size="medium"
                            class="ibps-mr-5"
                            :color="'danger' | optionsFilter(colorOptions,'color','type')"
                            :text-color="'danger' | optionsFilter(colorOptions,'textColor','type')"
                            @click.stop="toggleBtn('o')"
                          >
                            更多<van-icon :name="toggle!==field.id+'o' ? 'arrow-down': 'arrow-up'" /></van-tag>
                        </template>
                      </template>
                      <div v-if="getShowBtnByRemove().length >num && toggle===field.id+'o'" v-clickoutside="outFn" @click.stop="stopClick">
                        <div class="btn-pop-top" />
                        <div class="btn-pop">
                          <div
                            v-for="(button,j) in getShowBtnByRemove().slice(num-1) "
                            :key="button.key+j"
                            class="btn-pop-text"
                            @click.stop="handleActionEvent(button)"
                          >
                            {{ button.label }}
                          </div>
                        </div>
                      </div>

                    </div>
                  </div>
                </template>
              </van-collapse-item>
            </template>

          </van-field>
        </template>
      </template>
    </van-collapse>

    <!-- 弹窗-->
    <van-popup
      v-if="dialogMode"
      v-model="dialogPopup"
      class="ibps-fullscreen-popup"
    >
      <van-nav-bar
        :title="field.label"
        :right-text="$t('common.button.confirm')"
        @click-left="closePopup"
        @click-right="dialogConfirm"
      >
        <template #left>
          <van-icon name="cross" class="ibps-nav-bar__close-icon" />
        </template>
      </van-nav-bar>

      <div class="ibps-fixed-navbar">
        <ibps-dynamic-form-item
          v-for="(column) in columns"
          ref="dialogForm"
          :key="column.name"
          v-model="dialogData[column.name]"
          :field="column"
          :data="dialogFormData"

          :rights="rights[column.name]"
          :params="params"

          @cinput="handleDialogInput($event)"
        />
      </div>
    </van-popup>
  </div>
</template>
<script>
import FormOptions from '../constants/formOptions'
import FormUtil from '../utils/formUtil'
import FormFieldUtil from '../utils/formFieldUtil'
import { hasPermission } from '../constants/buttonTypes'
import { colorOptions } from '@/constants/btnColor'
import clickoutside from '@/utils/clickoutside'

import JForm from '../utils/JForm'// 自定义脚本
const COLLAPSE_NAME_KEY = 'table_'
export default {
  name: 'form-table',
  directives: { clickoutside },
  props: {
    value: [Array, Object, String], // 值
    formData: [Array, Object], // 表单数据
    field: {
      type: Object,
      required: true
    },
    rights: {
      type: [String, Object]
    },
    readonlyRights: { // 只读
      type: Boolean,
      default: false
    },
    required: {
      type: Boolean,
      default: false
    },
    rules: {
      type: Array
    },
    readonly: {
      type: Boolean,
      default: false
    },
    readonlyStyle: {
      type: String,
      default: 'text'
    },
    isLink: Boolean,
    mainCode: String, // 主表名
    // 扩展参数
    params: Object,
    num: {
      type: Number,
      default: 3
    },
    descPosition: String
  },
  data() {
    const activeCollapseNames = []
    let val = []
    if (this.$utils.isNotEmpty(this.value)) {
      val = this.value || []
      this.value.forEach((e, i) => {
        activeCollapseNames.push(COLLAPSE_NAME_KEY + i)
      })
    }

    return {
      activeCollapseNames: activeCollapseNames,
      collapseNameKey: COLLAPSE_NAME_KEY,
      dataModel: val,
      fieldRights: {}, // 子表配置权限
      tableRights: FormOptions.t.PERMISSIONS.EDIT, // 子表权限
      columnsRights: {}, // 子表字段权限
      buttonsRights: {}, // 子表按钮权限

      customDialogVisible: false,
      customDialogKey: '',
      customDialogDynamicParams: {},
      customDialogCustom: {},

      formDialogVisible: false,
      dialogFormDef: {},
      dialogFormData: {},
      dialogFormIndex: -1,

      importTableDialogVisible: false,

      inputValue: '',
      toggle: this._getItem(),
      colorOptions
    }
  },
  computed: {
    thatSocpe() {
      return this
    },
    models() {
      return this.formData
    },
    fieldOptions() {
      const fieldOptions = this.field.field_options || {}
      fieldOptions.default_value_type = fieldOptions.default_value_type || 'fixed'
      return fieldOptions
    },

    toolbarButtons() {
      return this.filterButtons('toolbar')
    },
    manageButtons() {
      return this.filterButtons('manage')
    },
    mode() {
      return this.field.field_options.mode || 'inner'
    },
    dialogMode() { // 弹窗模式
      return false
      // TODO 弹窗模式有bug 暂时屏蔽
      // this.tableMode === 'dialog'
    },
    relation() {
      return this.fieldOptions['relation'] || 'one2More'
    },
    isOne2One() {
      return this.relation === 'one2one'
    },
    // 暂无合计
    // showSummary() {
    //   return this.field.field_options.summary || false
    // },
    // sumText() {
    //   return this.field.field_options.sum_text || '合计'
    // },
    // hasSummaryMethod() {
    //   return this.field.field_options.summary_method || false
    // },
    code() {
      return this.field.name || ''
    },
    columns() {
      return this.field.field_options.columns || []
    },
    nameColumns() {
      return FormFieldUtil.getSubDisplayColumns(this.columns)
    },
    displayColumns() {
      const displayColumns = []
      const traverse = (fields) => {
        fields.forEach((field) => {
          if (FormOptions.t.NESTED_FIELD_TYPES.includes(field.field_type)) {
            const columns = field.field_options.columns
            columns.forEach(child => {
              traverse(child.fields)
            })
          } else {
            if (this.$utils.toBoolean(field.field_options.display, true)) {
              displayColumns.push(field)
            }
          }
        })
      }
      traverse(this.columns)
      return displayColumns
    },
    buttons() {
      const buttons = this.field.field_options.buttons || []
      const bs = []
      buttons.forEach(button => {
        const b = JSON.parse(JSON.stringify(button))
        b.key = button.type
        b.type = button.style
        b.style = button.style
        b.icon = 'ibps-icon-' + button.icon
        bs.push(b)
      })
      return bs
    },
    tableReadonly() {
      return this.readonlyRights ? true : this.tableRights === FormOptions.t.PERMISSIONS.READ
    },
    tableHidden() {
      return this.tableRights === FormOptions.t.PERMISSIONS.HIDE
    },
    formula() {
      return this.params.responseFormula ? this.params.responseFormula : null
    },
    linkages() {
      return this.params.responseLinkages ? this.params.responseLinkages : null
    }
  },
  watch: {
    value: {
      deep: true,
      immediate: true,
      handler(val, oldVal) {
        this.dataModel = val
        this.inputValue = this.$utils.isNotEmpty(val) ? JSON.stringify(val) : ''
      }
    },
    dataModel: {
      deep: true,
      handler(val, oldVal) {
        this.$emit('update:value', val)
      }
    },
    rights: {
      handler(val, oldVal) {
        if (val !== oldVal) {
          this.fieldRights = val || {}
        }
      },
      deep: true,
      immediate: true
    },
    // 字段权限
    fieldRights: {
      handler(fieldRights) {
        if (this.$utils.isNotEmpty(fieldRights) && this.$utils.isPlainObject(fieldRights)) {
          this.tableRights = this.getRealRights(fieldRights['rights'] || FormOptions.t.PERMISSIONS.EDIT)
          this.columnsRights = this.getColumnsRights(fieldRights['columns'])
          this.buttonsRights = this.getButtonsRights(fieldRights['buttons'])
        } else {
          this.tableRights = FormOptions.t.PERMISSIONS.EDIT
          this.columnsRights = this.getColumnsRights({})
          this.buttonsRights = this.getButtonsRights({})
        }
      },
      deep: true,
      immediate: true
    },
    activeCollapseNames() {
      // console.info(this.activeCollapseNames)
    }
  },
  mounted() {
    this.$nextTick(() => {
      if (this.mode === 'block') {
        const key = this.collapseNameKey + '0'
        if (!this.activeCollapseNames.includes(key)) {
          this.activeCollapseNames.push(key)
        }
      }
    })
  },
  methods: {
    /**
     * 获取本地缓存
     */
    _getItem() {
      return localStorage.getItem('btnClose')
    },
    /**
     * 本地缓存
     */
    _setItem(val) {
      localStorage.setItem('btnClose', val)
    },
    /**
     * 切换按钮
     */
    toggleBtn(i) {
      // const item = this._getItem()
      const item = this.toggle
      if (item && item === this.field.id + '' + i) {
        this.toggle = ''
      } else {
        this.toggle = this.field.id + '' + i
      }
      this._setItem(this.toggle)
    },
    outFn() {
      this.toggle = ''
      this._setItem(this.toggle)
    },
    stopClick() {
    },
    /**
     * 获取需要显示的这样按钮
     */
    getShowBtn() {
      if (!this.toolbarButtons) return []
      return this.toolbarButtons.filter(el => !(el.key === 'remove' && this.mode === 'block' && this.dataModel.length === 1))
    },
    getShowBtnByRemove() {
      if (!this.toolbarButtons) return []
      return this.toolbarButtons.filter(el => el.key !== 'remove')
    },
    columnHidden(column) { // 是否隐藏
      return this.columnsRights[column.name] === FormOptions.t.PERMISSIONS.HIDE || column.field_type === 'hidden'
    },
    /**
     * 获取真实的权限
     */
    getRealRights(rights) {
      if (this.readonlyRights) {
        return rights === FormOptions.t.PERMISSIONS.HIDE ? rights : FormOptions.t.PERMISSIONS.READ
      } else {
        return rights
      }
    },
    getColumnsRights(rights = {}) {
      const columnsRights = {}
      if (this.nameColumns && this.nameColumns.length > 0) {
        this.nameColumns.forEach(column => {
          columnsRights[column.name] = this.getRealRights(rights[column.name] || FormUtil.getDefaultRigths(column))
        })
      }
      return columnsRights
    },
    getButtonsRights(rights = {}) {
      if (this.$utils.isEmpty(rights)) {
        const buttonsRights = {}
        if (this.$utils.isNotEmpty(this.buttons)) {
          this.buttons.forEach(button => {
            buttonsRights[button.key] = FormOptions.t.PERMISSIONS.SHOW
          })
        }
        return buttonsRights
      } else {
        return rights || {}
      }
    },

    tableRowClassName({ row, rowIndex }) {
      // 把每一行的索引放进row
      row.$index = rowIndex
    },
    handleSelectionChange(selection) {
      this.multipleSelection = selection
    },
    handleRowClick(row, event, column) {
      this.$refs.elTable.toggleRowSelection(row)
    },
    filterButtons(position) {
      if (this.tableReadonly) return
      const bs = []
      this.buttons.forEach(button => {
        if (hasPermission(button.key, position) && // 有位置权限
        (!button.position || button.position === 'all' || button.position === position) &&// 有位置权限
        (this.$utils.isEmpty(this.buttonsRights[button.key]) || this.buttonsRights[button.key] !== FormOptions.t.PERMISSIONS.HIDE) // 有按钮权限
        ) {
          const b = JSON.parse(JSON.stringify(button))
          b.position = position
          bs.push(b)
        }
      })
      return bs
    },
    handleActionEvent(button, index) {
      // 前置事件
      this.beforeScript(button, index, (result) => {
        if (!result) {
          return
        }
        switch (button.key) {
          case 'add':
            // 新增自定义按钮
            if (button.enabledCustom === 'Y') {
              this.handleAddCustomDialog(button)
            } else {
              this.handleAdd()
            }
            break
          case 'edit':
            this.handleDialogMode(index)
            break
          case 'remove':
            this.handleRemove(button, index)
            break
          case 'import':
            this.handleImport(button, index)
            break
          case 'export':
            this.handleExport(button, index)
            break
          default:
            break
        }
      })
      this._setItem('')
    },
    // 添加
    async handleAdd() {
      // if (this.mode === 'dialog') {
      //   this.handleDialogMode()
      // } else {
      const defaultValue = await FormUtil.getTableDefaultData(this.field)
      await this.addData(JSON.parse(JSON.stringify(defaultValue)))
      // }
    },
    // 新增数据
    addData(data) {
      this.dataModel.push(data)
      const dataLength = this.dataModel.length - 1
      // 初始化运行公式计算
      this.initRunCalFormula(dataLength)
      const key = this.collapseNameKey + dataLength
      if (!this.activeCollapseNames.includes(key)) {
        this.activeCollapseNames.push(key)
      }

      // 后置事件
      this.afterScript('add', 'toolbar')
    },

    handleRemove(button, index) {
      if (this.dataModel.length === 0) {
        return
      }
      const position = button.position

      this.$dialog.confirm({
        title: '提示',
        message: '确定删除？'
      }).then(() => {
        this.dataModel.splice(index, 1)
        // TODO: 处理折叠面板

        // 后置事件
        this.afterScript('remove', position, {
          selection: [index],
          index: index
        })
      })
    },
    // 初始化运行公式计算
    initRunCalFormula(row) {
      // 不需要字段的进行公式计算 比如获取但其当前时间，随机数
      FormUtil.runCalFormula(this, this.formula[FormUtil.NOT_NEED_FIELD], this.mainCode, row)
    },
    // =====================对话框模式数据处理=====================

    handleDialogMode(index) {
      const data = this.$utils.isNotEmpty(index) ? this.dataModel[index] : {}
      this.dialogFormData = {
        responses: JSON.parse(JSON.stringify(data)),
        // 表单字段权限
        permissions: {
          fields: this.columnsRights
        }
      }
      this.dialogFormIndex = this.$utils.isNotEmpty(index) ? index : -1
      this.dialogFormDef = {
        code: this.field.name,
        attrs: {
          hide_name: true
        },
        fields: this.columns
      }
      // 表单
      this.formDialogVisible = true
    },
    /**
     * 对话框模式表单返回值
     */
    handleFormDialogActionEvent(key, data) {
      if (this.dialogFormIndex > -1) {
        this.dataModel.splice(this.dialogFormIndex, 1, data)
        // 后置事件
        this.afterScript('edit', 'manage', {
          index: this.dialogFormIndex
        })
      } else {
        this.addData(data)
      }
      this.formDialogVisible = false
    },
    // =====================自定义对话框=====================

    handleAddCustomDialog(button) {
      this.customDialogKey = button.dialog
      this.customDialogDynamicParams = {}
      this.customDialogCustom = button.custom
      setTimeout(() => {
        this.customDialogVisible = true
      }, 10)
    },
    async handleCustomDialogActionEvent(key, datas) {
      const linkLinkage = this.customDialogCustom['link_linkage']
      if (this.$utils.isEmpty(linkLinkage)) {
        return
      }
      const defaultValue = await FormUtil.getTableDefaultData(this.field)
      for (let i = 0; i < datas.length; i++) {
        const data = datas[i]
        const model = JSON.parse(JSON.stringify(defaultValue))
        for (let i = 0; i < linkLinkage.length; i++) {
          const item = linkLinkage[i]
          const fieldName = item.field
          if (model.hasOwnProperty(fieldName)) {
            model[fieldName] = data[item.name] || ''
          }
        }
        this.dataModel.push(model)
      }
      // 后置事件
      this.afterScript('add', 'toolbar')
    },
    summaryMethod(param) {
      if (this.showSummary) {
        return JForm._summaryMethod(this, this.field.name, param)
      }
    },
    hasScript() {
      return true
    },
    // 前置脚本
    beforeScript(button, index, callback) {
      if (!this.hasScript()) {
        if (callback) {
          const flag = true
          callback(flag)
        }
        return
      }
      const action = button.key === 'custom' ? (button.code || button.code + index) : button.key
      const params = {
        button: button,
        index: index
      }
      if (!callback) {
        callback = () => {

        }
      }
      JForm._beforeSubButton(this, action, button.position, params, callback)
    },
    // 后置脚本
    afterScript(action, position, params, callback) {
      if (!this.hasScript()) {
        if (callback) {
          const flag = true
          callback(flag)
        }
        return
      }

      if (!params) {
        params = {}
      }
      params.button = this.getButtonByKey(action)
      if (!callback) {
        callback = () => {

        }
      }
      JForm._afterSubButton(this, action, position, params, callback)
    },
    getButtonByKey(action) {
      return this.buttons.find((button) => {
        return button.key === action
      })
    },
    /**
     * 更新字段值（主表或其他子表）
     */
    updateFormData(name, value) {
      this.$emit('change-data', name, value)
    },
    // 设置行数据
    setRowData(row, name, value) {
      this.dataModel[row][name] = value
    },
    // 设置行数据
    getRowData(row, name) {
      return this.dataModel[row][name]
    },
    /**
     * 获取表单值
     */
    getData(key) {
      return this.formData[key]
    },
    /**
     * 设置表单值
     */
    setData(name, value) {
      this.updateFormData(name, value)
    },

    // ======表单验证============
    getEl() {
      if (!this.$refs.formItem) { return }
      const $validate = []
      this.$refs.formItem.forEach(el => {
        $validate.push(el)
      })
      return $validate
    },
    getFormValidator() {
      if (!this.$refs.formItem) { return }
      const $validate = []
      this.$refs.formItem.forEach(el => {
        const v = new Promise((resolve, reject) => {
          el.getFormValidator().validate().then((result) => {
            resolve(result)
          })
        })
        $validate.push(v)
      })
      return Promise.all($validate)
    }
  }
}
</script>
<style lang="scss">
  .ibps-table-wrapper{
    padding: 10px 0;
    // background-color: #f2efef;
    .btn-pop,.btn-pop-top{
      position: absolute;
      z-index: 1000;
      top: 34px;
    }
    .btn-pop{
      background: #4C4C4C;
      color:  #FFFFFF;
      border-radius: 4px;
      text-align: left;
      padding-left: 14px;
      right: 4px;
      min-width: 120px;
      .btn-pop-text{
        padding: 12px 0;
        border-bottom: 1px solid rgba(229,229,229,0.3);
      }
    }
    .btn-pop-top{
      border: 6px solid transparent;
      border-bottom-color: #4C4C4C;
      top: 22px;
      right: 18px;
    }
    .van-cell,.van-cell__value{
      overflow: visible;
    }
    .table-field{
      padding:0 ;
    }
    .table-cell-icon{
      display: flex;
      align-items: center;
    }

    .van-collapse-item__title {
      padding:0 ;
      background-color: #f8f8f8;
      .table-cell{
        background-color: #f8f8f8;
        // padding-right: 0;
      }
      .van-cell__title{
        font-size: 12px;
        color: #999;
      }
        .van-cell__right-icon{
          margin-top: 8px;
        }
    }
    .van-collapse-item__content{
      padding:0
    }

  }
</style>
