<template>
  <div class="select-table">
    <div class="select-table-box" :style="{flexDirection: direction}">
      <page-layout-list class="dialog-table">
        <template #filter v-if="searchFieldList && searchFieldList.length>0">
          <cip-search-form v-model:model="searchFilter" v-model:defaultModel="defaultSearchModel" :field-list="searchFieldList" @search="handleSearch" :hideSearch="hideSearch"></cip-search-form>
        </template>
        <cip-table v-if="checkType === 'radio'"
                   :hide-index="hideIndex"
                  :data="itemList"
                  :columns="tableColumns"
                  :offset="offset"
                  ref="tableRef"
                  size="default"
                  :select-type="checkType"
                  :select-radio="selectRadio"
                  :select-label="optionProps.value"
                  @current-change="currentChange"
                  v-loading="listLoading">
        </cip-table>
        <cip-table v-if="checkType === 'checkbox'"
                   :hide-index="hideIndex"
                  :data="itemList"
                  :columns="tableColumns"
                  :offset="offset"
                  ref="tableRef"
                  size="default"
                  :select-type="checkType"
                  @select="onSelect"
                  @select-all="onSelectAll"
                  :selectable="selectable"
                  v-loading="listLoading">
        </cip-table>
        <template #pagination v-if="withPagination">
          <cip-pagination v-model:offset="offset"
                          v-model:limit="limit"
                          :total="total"
                          :current-page="currentPage"
                          layout="total, sizes, prev, next, jumper"
                          prev-text="上一页"
                          next-text="下一页"
                          @refresh="getItemList"></cip-pagination>
        </template>
      </page-layout-list>
      <slot name="group"></slot>
      <tags :class="{'limited-height': direction.indexOf('column') !== -1}" v-if="!$slots.group && withTags" class="dialog-tags" :style="{flexBasis: direction.includes('row')?'220px':'100px'}" :options="checkOptions" :keyProp="optionProps" @update:options="changeOptions"></tags>
    </div>
  </div>
</template>

<script>
import { useCurd } from '@cip/hooks/use-curd'
import { useTableCacheSelect } from '@cip/components/hooks/table-cache-select'
import { ref, computed, nextTick, watch, watchEffect } from 'vue'
import { ElLoading } from 'element-plus'
import PageLayoutList from '@cip/components/page-layout/list'
import CipSearchForm from '@cip/components/cip-search-form'
import CipTable from '@cip/components/cip-table'
import CipPagination from '@cip/components/cip-pagination'
import Tags from './tags'
import { isEmpty } from '@cip/utils/util'
export default {
  components: { Tags, PageLayoutList, CipSearchForm, CipTable, CipPagination },
  directives: {
    loading: ElLoading.directive
  },
  props: {
    entity: {},
    curdFn: {},
    tableColumns: {},
    searchFieldList: {},
    modelValue: [String, Object],
    otherValue: String,
    checkedItem: {},
    searchCustomize: {
      type: Boolean,
      default: false
    },
    optionProps: {
      type: Object,
      default: () => ({ label: 'label', value: 'value' })
    },
    defaultSearchFilter: {
      type: Object
    },
    checkType: {
      type: String,
      default: 'radio'
    },
    hideSearch: Boolean,
    withPagination: { // 是否显示分页
      type: Boolean,
      default: true
    },
    hideIndex: { type: Boolean, default: undefined },
    withTags: { type: Boolean, default: true },
    direction: { type: String, default: 'row' } // 布局方向
  },
  emits: ['selectValue', 'customizeSearch'],
  setup (props, { emit }) {
    const checkOptions = computed(() => {
      return cacheSelectedList.value.length === 0 ? props.checkedItem : cacheSelectedList.value
    })

    // 右侧数据改变
    const changeOptions = (item) => {
      cacheSelectedList.value = item
      updateSelectValue(item)
      handleSelectShow()
    }
    const updateSelectValue = (item) => {
      emit('selectValue', item)
    }

    const tableRef = ref()
    const CURD = useCurd(props.entity, { ...props.curdFn, itemType: props.itemType })
    const { itemList, getItemList, searchFilter, search } = CURD
    const defaultSearchModel = ref()
    if (props.defaultSearchFilter) {
      defaultSearchModel.value = { ...props.defaultSearchFilter }
      searchFilter.value = { ...defaultSearchModel.value }
    }
    getItemList()

    const primaryKey = ref(props.optionProps.value)
    const { cacheSelectedList, onSelect, onSelectAll } = useTableCacheSelect(itemList, primaryKey.value, val => {
      // 不为空的值才进行更新
      const selectRows = val.filter(v => v[primaryKey.value])
      if (selectRows.length > 0) {
        updateSelectValue(val)
      }
    })

    // 外层触发请求
    const getTableList = (item = {}) => {
      searchFilter.value = item
      getItemList()
    }

    // 已选择的radio
    const selectRadio = computed(() => {
      return props.checkedItem[primaryKey.value] || radioCache.value
    })

    // radio类型时的缓存
    const radioCache = computed(() => {
      const cache = itemList.value.find(v => v[primaryKey.value] === props.modelValue)
      return cache ? cache[primaryKey.value] : undefined
    })
    const currentChange = (currentRow, oldCurrentRow) => {
      // 单选不能取消，只能有值时才填入
      if (currentRow) {
        updateSelectValue(currentRow)
      }
    }

    // checkbox类型更新选中视图
    const showSelectedView = (rows, select) => {
      nextTick(() => {
        rows.forEach(row => {
          tableRef.value.cipTableRef.toggleRowSelection(row, select)
        })
      })
    }
    // tag组件传入值需要更新table选中视图
    // 目前暂按照String化处理，后续想一下如何处理
    const handleSelectShow = () => {
      const selectedPropsCode = cacheSelectedList.value.map(button => button[primaryKey.value])
      const rows = itemList.value.filter(item => {
        return !selectedPropsCode.map(v => String(v)).includes(String(item[primaryKey.value]))
      })
      showSelectedView(rows, false)
    }
    if (props.checkType === 'checkbox') {
      // 分页切换时缓存数据处理
      watch(itemList, list => {
        cacheHandle()
      })
    } else {
      const unWatch = watchEffect(() => {
        if (props.checkedItem[primaryKey.value]) {
          const checkItem = itemList.value.filter(item => item[primaryKey.value] === props.checkedItem[primaryKey.value])[0]
          if (checkItem) {
            updateSelectValue(checkItem)
            unWatch()
          }
        }
      })
    }
    // 缓存数据处理
    const cacheHandle = () => {
      if (cacheSelectedList.value.length === 0) {
        cacheSelectedList.value = props.checkedItem
      }
      const cacheSelectButtonCode = cacheSelectedList.value.map(button => button[primaryKey.value])
      const rows = itemList.value.filter(item => {
        const selectList = props.checkedItem || cacheSelectButtonCode.includes(item[primaryKey])
        // 从列表中匹配已选中或者缓存中的值
        return selectList.findIndex(v => {
          // primaryKey.value匹配不上的时候，默认为未选中
          if (isEmpty(v[primaryKey.value]) || isEmpty(item[primaryKey.value])) {
            return false
          } else {
            return String(v[primaryKey.value]) === String(item[primaryKey.value])
          }
        }) !== -1
      })
      // 匹配上的值进行选中操作
      showSelectedView(rows, true)
    }
    // 所有column可选
    const selectable = () => () => true

    // 搜索
    const handleSearch = () => {
      search()
    }

    return {
      changeOptions,
      checkOptions,
      getTableList,
      handleSearch,
      ...CURD,
      defaultSearchModel,
      tableRef,
      selectable,
      selectRadio,
      currentChange,
      onSelect,
      onSelectAll,
      cacheSelectedList
    }
  }
}
</script>

<style lang="less" scoped>
.select-table{
  flex: 1;
  .select-table-box{
    display: flex;
    background: @background;
    padding: 20px;
  }
  .dialog-table{
    flex: 1;
    margin: 0 15px 15px 0;
    padding: 0;
  }
  .dialog-tags{
    padding: 8px 0;
    flex-basis: 220px;
  }
  .limited-height{
    max-height: 200px;
    overflow: auto;
  }
}
</style>
