<template>
  <div
    class="d2-crud d2-crud-x"
    :class="{'d2-crud-height100':(options && options.height==='100%')}"
  >
    <div class="d2-crud-header" v-if="$slots.header">
      <slot name="header"/>
    </div>
    <div class="d2-crud-body" v-if="options && options.hide === true">
      <slot name="body"/>
    </div>
    <div class="d2-crud-body"
         v-loading="loading"
         :element-loading-text="getAttribute(loadingOptions,'text', null)"
         :element-loading-spinner="getAttribute(loadingOptions,'spinner', null)"
         :element-loading-background="getAttribute(loadingOptions,'background', null)"
         v-else >
      <component
        :is="(options.lineEdit&&options.lineEdit.validation)?'el-form':'div'"
        style="height:100%"
        ref="lineEditForm"
        :model="lineEditor.form"
        :rules="handleFormRulesMode()"
        :formMode="formMode"
        v-bind="formOptions"
        labelWidth="0"
      >
      <component
        :is="getTableImpl(options.tableType)"
        ref="elTable"

        :data="d2CrudData"
        v-bind="options"
        @select="handleSelect"
        @sort-change="handleSortChange"
        @cell-mouse-enter="handleCellMouseEnter"
        @cell-mouse-leave="handleCellMouseLeave"
        @cell-click="handleCellClick"
        @cell-dblclick="handleCellDblclick"
        @row-click="handleRowClick"
        @row-contextmenu="handleRowContextmenu"
        @row-dblclick="handleRowDblclick"
        @header-click="handleHeaderClick"
        @header-contextmenu="handleHeaderContextmenu"
        @current-change="handleCurrentChange"
        v-on="_tableListeners"
      >
        <template v-if="thisIsVxeTable">
          <component
            :is="getTableColumnImpl()"
            v-if="(selectionRow || selectionRow === '') "
            type="checkbox"
            :title="handleAttribute(selectionRow.title, '')"
            v-bind="forBindProps(selectionRow)"
          />
          <component
            v-if="(expandRow || expandRow === '')"
            :is="getTableColumnImpl()"
            type="expand"
            :title="handleAttribute(expandRow.title, '')"
            v-bind="forBindProps(expandRow)"
          >
            <template slot="content" slot-scope="scope">
              <slot name="expandSlot" :rowIndex="scope.$rowIndex" :index="scope.$rowIndex" :row="scope.row"/>
            </template>
          </component>
          <component
            :is="getTableColumnImpl()"
            v-if="indexRow || indexRow === ''"
            type="seq"
            :title="handleAttribute(indexRow.title, '')"
            v-bind="forBindProps(indexRow)"
          />
        </template>
        <template v-else>
          <component
            :is="getTableColumnImpl()"
            v-if="(selectionRow || selectionRow === '') "
            type="selection"
            :label="handleAttribute(selectionRow.title, '')"
            v-bind="forBindProps(selectionRow)"
          />

          <component
            v-if="(expandRow || expandRow === '') "
            :is="getTableColumnImpl()"
            type="expand"
            :label="handleAttribute(expandRow.title, '')"
            v-bind="forBindProps(expandRow)"
          >
            <template  slot-scope="scope">
              <slot name="expandSlot" :scope="scope" :index="scope.$index" :row="scope.row"/>
            </template>
          </component>

          <component
            :is="getTableColumnImpl()"
            v-if="indexRow || indexRow === ''"
            type="index"
            :label="handleAttribute(indexRow.title, '')"
            v-bind="forBindProps(indexRow)"
          />
        </template>

        <!-- 使用d2-column递归组件 -->
        <d2-column v-for="(item,index) in columns"
                   :key="buildColumnKey(item,index)"
                   :item="item"
                   :tableType="options.tableType"
                   @cell-data-change="handleCellDataChange"
                   @cell-component-ready="handleCellComponentReady"
                   @cell-component-custom-event="handleCellComponentCustomEvent"
        >
            <template slot-scope="scope" :slot="item.key+'Slot'">
              <template v-if="item.rowSlot">
                <slot :name="item.key+'Slot'" :row="scope.row" :index="scope.index" :rowIndex="scope.index"/>
              </template>
            </template>
        </d2-column>

        <component
          :is="getTableColumnImpl(options.tableType)"
          v-if="rowHandle"
          v-bind="forBindPropsRowHandle(rowHandle)"
        >
          <template slot-scope="scope">

            <template
              v-for="(item, index) in (isShowLineEditModeBtns(scope)?_lineEditModeBtns:_handleFlatBtns)"
            >
              <d2-button :key="index"
                         v-if="handleRowHandleButtonShow(item.show, scope)"
                         :disabled="handleRowHandleButtonDisabled(item.disabled, scope)"
                         :icon="handleAttribute(item.icon,null,scope)"
                         :type="handleAttribute(item.type,null,scope)"
                         @click.stop="item.doClick(scope)"
                         :label="handleAttribute(item.text,null,scope)"
                         v-bind="item"
              />
            </template>

            <!-- 即将废弃 -->
            <slot name="rowHandle" :index="scope.$index" :rowIndex="scope.$rowIndex" :row="scope.row" ></slot>
            <slot name="rowHandleSlot" :index="scope.$index" :rowIndex="scope.$rowIndex" :row="scope.row"></slot>
            <!-- 下拉按钮菜单 -->
            <span class="d2p-handle-row-dropdown" v-if="!isShowLineEditModeBtns(scope) && rowHandle.dropdown &&  _handleDropdownBtns && _handleDropdownBtns.length>0" >
              <el-dropdown @command="handleRowHandleDropdownItemClick($event,scope)">
                <d2-button
                  :disabled="handleRowHandleButtonDisabled(rowHandle.dropdown.disabled, scope)"
                  :type="handleAttribute(rowHandle.dropdown.type,'primary',scope)"
                  :size="handleAttribute(rowHandle.dropdown.size,'small',scope)"
                  v-bind="rowHandle.dropdown"
                >
                  {{handleAttribute(rowHandle.dropdown.text,'更多',scope)}}
                  <i class="el-icon-arrow-down el-icon--right"></i>
                </d2-button>
                <el-dropdown-menu slot="dropdown"  >
                  <template v-for="(item, index) in _handleDropdownBtns">
                    <el-dropdown-item :key="index"
                                      v-if="handleRowHandleButtonShow(item.show, scope)"
                                      :icon="handleAttribute(item.icon,null,scope)"
                                      :command="item"
                                      :disabled="handleRowHandleButtonDisabled(item.disabled, scope)">
                      {{ handleAttribute(item.text,null,scope) }}
                    </el-dropdown-item>
                  </template>

                </el-dropdown-menu>
              </el-dropdown>
            </span>

          </template>

        </component>
      </component>
      </component>
    </div>
    <div class="d2-crud-footer">
      <div class="d2-crud-pagination" v-if="pagination">
        <el-pagination
          v-bind="pagination"
          @size-change="handlePaginationSizeChange"
          @current-change="handlePaginationCurrentChange"
          @prev-click="handlePaginationPrevClick"
          @next-click="handlePaginationNextClick"
        >
          <slot name="PaginationPrefixSlot" />
        </el-pagination>
      </div>
      <slot name="footer"/>
    </div>

    <!-- 表单对话框 -->
    <component
      :is="'el-'+(formOptions.type || 'dialog')"
      class="d2-crud-dialog"
      :visible="isDialogShow"
      v-on:update:visible="handleDialogShowUpdate"
      :before-close="handleDialogCancel"
      v-d2p-drag-dialog="handleAttribute(formOptions.draggable,true)"
      :class="{'d2p-drag-dialog':handleAttribute(formOptions.draggable,true),'d2p-form-drawer':isFormDrawer,'d2p-max-height':formOptions.maxHeight}"
      v-bind="formOptions"
    >
      <template slot="title">
       <span> {{getFormTitle()}}</span>
        <slot name="FormHeaderSlot" :mode="formMode" :data="formData"  :form="formData" :row="formDataStorage"/>
        <button v-if="formOptions.fullscreen!=null" type="button"  class="el-dialog__headerbtn fullscreen" @click="formOptions.fullscreen = !formOptions.fullscreen" ><i class="el-dialog__close el-icon el-icon-full-screen"/></button>
      </template>
      <el-form
        v-if="isFormShow"
        ref="form"
        :model="formData"
        :rules="handleFormRulesMode()"
        :fullscreen="formOptions.fullscreen"
        :formMode="formMode"
        @submit.native.prevent
        v-bind="formOptions"
      >
        <el-row v-bind="formOptions" >
          <template v-for="(item,key, index) in formTemplateStorage" >
            <el-col :key="index"
              v-if="getTemplateComponentAttr(item,'show', true,getContext(key))"
              :span="getTemplateComponentAttr(item,'span', 24)"
              :offset="getTemplateComponentAttr(item,'offset', 0)"
            >
              <d2-form-item
                :template="item"
                :colKey="key"
                :formData="formData"
                :ref="'form_item_'+key"
                :formMode="formMode"
                :getColumn="getFormComponentRef"
                @form-data-change="handleFormDataChange"
                @form-component-ready="handleFormComponentReady"
                @form-component-custom-event="handleFormComponentCustomEvent"
              >
                <template :slot="key+'FormSlot'">
                    <slot :name="key+'FormSlot'" :form="formData" :mode="formMode" :row="formDataStorage"/>
                </template>
                <template :slot="key+'HelperSlot'">
                    <slot :name="key+'HelperSlot'" :form="formData" :mode="formMode" :row="formDataStorage"/>
                </template>
              </d2-form-item>
            </el-col>
          </template>
        </el-row>

        <el-collapse v-if="formTemplateGroupStorage" v-model="formGroupsActive" :accordion="formTemplateGroupStorage.accordion"    >
          <template v-for="(group,groupKey) in formTemplateGroupStorage.groups"   >
            <el-collapse-item :key="groupKey" :name="groupKey" :disabled="group.disabled"  v-if="getAttribute(group,'show', true,{mode:formMode,form:formData})">
              <template slot="title" >
                <h3 v-if="!$scopedSlots[groupKey+'GroupTitleSlot']" class="group-title" ><i v-if="group.icon" class="header-icon" :class="group.icon"/> {{group.title}}</h3>
                <slot :name="groupKey+'GroupTitleSlot'" :groupKey="groupKey" :group="group"/>
              </template>
              <el-row v-bind="formOptions">
                <template v-for="(item,key, index) in group.columns" >
                  <el-col :key="index"
                          v-if="getTemplateComponentAttr(item,'show', true,getContext(key))"
                          :span="getTemplateComponentAttr(item,'span', 24)"
                          :offset="getTemplateComponentAttr(item,'offset', 0)"
                  >
                    <d2-form-item
                      :template="item"
                      :colKey="key"
                      :formData="formData"
                      :ref="'form_item_'+key"
                      :formMode="formMode"
                      :getColumn="getFormComponentRef"
                      @form-data-change="handleFormDataChange"
                      @form-component-ready="handleFormComponentReady"
                      @form-component-custom-event="handleFormComponentCustomEvent"
                    >
                      <template :slot="key+'FormSlot'">
                        <slot :name="key+'FormSlot'" :form="formData" :row="formDataStorage"/>
                      </template>
                      <template :slot="key+'HelperSlot'">
                        <slot :name="key+'HelperSlot'" :form="formData" :row="formDataStorage"/>
                      </template>
                    </d2-form-item>
                  </el-col>
                </template>
              </el-row>
            </el-collapse-item>
          </template>
        </el-collapse>
        <div class="form-body-append">
          <slot name="FormBodyAppendSlot" :mode="formMode" :form="formData" :row="formDataStorage"/>
        </div>
      </el-form>
      <div class="d2p-form-footer" :slot="isFormDrawer?'default':'footer'" >
        <slot name="FormFooterSlot" :mode="formMode" :data="formData" :form="formData" :row="formDataStorage" />
        <el-button v-if="getAttribute(formOptions,'saveButtonShow', true)"
          :size="getAttribute(formOptions,'saveButtonSize', null)"
          :type="getAttribute(formOptions,'saveButtonType' ,null)"
          :icon="getAttribute(formOptions,'saveButtonIcon', null)"
          :disabld="getAttribute(formOptions,'saveButtonDisabled', false)"
          :loading="getAttribute(formOptions,'saveLoading', false)"
          @click="handleDialogSave"
        >
        {{ getAttribute(formOptions,'saveButtonText', '确定')}}
        </el-button>
      </div>
    </component>
  </div>
</template>

<script>
import base from './mixin/base'
import handleRow from './mixin/handleRow'
import data from './mixin/data'
import edit from './mixin/edit'
import add from './mixin/add'
import remove from './mixin/remove'
import dialog from './mixin/dialog'
import pagination from './mixin/pagination'
import exposeMethods from './mixin/exposeMethods.js'
import utils from './mixin/utils'
import D2Column from './components/d2-column'
import D2FormItem from './components/d2-form-item'
import D2Button from './components/d2-button/component'
import view from './mixin/view'

export default {
  name: 'd2-crud',
  provide: function () {
    return {
      d2CrudContext: {
        d2Crud: this,
        getForm: this.getFormData,
        getLineEditor: () => {
          return this.lineEditor
        }
      }
    }
  },
  data () {
    return {
      cells: {

      }
    }
  },
  mixins: [
    base,
    data,
    handleRow,
    edit,
    add,
    view,
    remove,
    dialog,
    pagination,
    exposeMethods,
    utils
  ],
  components: {
    D2FormItem,
    D2Column,
    D2Button
  },
  computed: {
    _tableListeners () {
      const events = this.options.events || {}
      if (this.isVxeTable()) {
        return {
          'checkbox-all': this.handleSelectAll,
          'checkbox-change': this.handleSelectionChange,
          ...events
        }
      } else {
        return {
          'select-all': this.handleSelectAll,
          'selection-change': this.handleSelectionChange,
          ...events
        }
      }
    }
  },
  methods: {
    handleFormDataChange (event) {
      this.$emit('form-data-change', { getComponent: this.getFormComponentRef, ...event })
    },
    handleFormComponentReady (event) {
      this.$emit('form-component-ready', event)
    },
    handleFormComponentCustomEvent (event) {
      this.$emit('form-component-custom-event', event)
    },
    handleCellDataChange (column) {
      this.$emit('cell-data-change', column)
    },
    handleCellComponentReady (column) {
      this.$emit('cell-component-ready', column)
    },
    handleCellComponentCustomEvent (column) {
      this.$emit('cell-component-custom-event', column)
    },
    handleDialogOpened (event) {
      // TODO 暂时无效
      this.$emit('form-dialog-opened', { event: event, form: this.formData, row: this.formDataStorage })
    },
    getFormComponentRef (key) {
      if (this.$refs) {
        const wrapper = this.$refs['form_item_' + key]
        if (wrapper && wrapper.length > 0 && wrapper[0]) {
          return wrapper[0].getComponentRef()
        }
      }
    },
    buildColumnKey (item, index) {
      return (item.key || '') + (item.uniqueKey || '') + index // + new Date().getTime()
    },
    getContext (key) {
      return {
        mode: this.formMode,
        key: key,
        value: this.formData[key],
        form: this.formData,
        row: this.formDataStorage
      }
    }
  }
}
</script>

<style lang="scss">

.d2-crud-x {
  display: flex;
  flex-direction: column;
  .d2p-handle-row-dropdown:first-child{
    margin-left:0px
  }
  .d2p-handle-row-dropdown{
    margin-left:10px
  }
  .d2-crud-header {
    /*border-bottom: 1px dotted rgba(0, 0, 0, 0.2);*/
  }
  .d2-crud-body {
    padding: 15px 0;
    overflow: hidden;
    flex-grow: 1;
  }
  .d2-crud-pagination {
    padding: 15px 0;
  }
  .form-item-helper{
    display: block;
    margin-top: 5px;
    margin-bottom: 5px;
    color: #737373;
    line-height: normal;
  }
  .el-collapse-item__wrap {
    padding-top: 7px;
  }
  .el-collapse-item__content{
    padding-left:30px;
    padding-right:30px;
  }
  &.d2-crud-height100{
    height:100%;
    .d2-crud-body{
      height: 100%;
    }
  }

  .d2-button{
    &.is-thin{
      &.el-button--small, &.el-button--small.is-round {
        padding: 9px 9px;
      }
      &.el-button--mini, &.el-button--mini.is-round {
        padding: 7px 7px;
      }
    }
  }
  .d2-crud-pagination{
    /*padding:0px 0;*/
    /*display: flex;*/
    /*align-items: center;*/
    .el-pagination{
      .prefix{
        button{
          background-color: #f4f4f5;
          min-width: 30px;
        }
      }
    }
  }
}

.d2-crud-dialog{
  .el-dialog__headerbtn{
    padding:10px;
    top:12px;
    &.fullscreen {
      right:55px;
    }
  }
  &.d2p-drag-dialog{
    .is-fullscreen{
      left:0px !important;
      top:0px !important;
      .el-dialog__header{
        cursor: auto !important;
      }
    }
  }
  &.d2p-max-height{
    .el-dialog{
      max-height:70vh;
      display: flex;
      flex-direction: column;

      &.is-fullscreen{
        max-height:100%;
      }
      .el-dialog__body{
        overflow-y: auto;
        flex:1;
      }
      .el-dialog__header{
        padding: 20px 20px 20px;
        border-bottom: 1px solid #eee;
      }
      .el-dialog__footer {
        padding: 10px 20px 10px;
        border-top: 1px solid #eee;
      }
    }
  }

  .el-form[formMode=view]{
    .el-form-item__label{
      color:#909090
    }
  }

  &.d2p-form-drawer{
    .el-drawer__body{
      padding:20px;
      overflow-y: scroll;
    }
    .d2p-form-footer{
      text-align: right;
    }
    .el-drawer__header {
      margin-bottom: 0px;
      padding: 20px 20px 20px;
      border-bottom: solid 1px #eee;
    }
    .el-drawer:focus{outline:none}
    .el-drawer__close-btn:focus{outline:none}
  }
}
.page-compact{
  .d2-container-full__body{
    padding:0px !important
  }
  .d2-crud-header{
    padding:10px;
    border-bottom:0px
  }
  .d2-crud .d2-crud-body{
    padding:0px;
  }
  .d2-crud-pagination{
    padding:10px 0;
  }
  .el-table--border {
    border-left: none;
  }
}

.d2-mb-2{margin-bottom: 2px}
.d2-mt-2{margin-top: 2px;}
.d2-mr-5{margin-right: 5px}
.d2-mr-10{margin-right: 10px}
</style>
