<template>
  <div class="kyb-select-con">
    <div v-if="!hideToolbar" class="toolbar q-pa-xs">
      <slot name="top" v-bind="{ queryParam, find }">
      <input
        class="q-ml-xs q-mr-xs input rounded-borders"
        v-model="keyword"
        placeholder="关键字"
        @input="find(keyword)"
      />
      <!-- showRight是附加到下面的右侧侧滑面板的模型 -->
      <q-btn
        icon="add"
        :color="canAddInner?'primary':'grey-6'"
        flat
        dense
        size="0.8em"
        @click="canAddInner=!canAddInner"
      >
        <q-tooltip>{{canAddInner?'可以添加':'不可添加'}}</q-tooltip>
      </q-btn>
      <q-btn
        icon="clear"
        :color="canDelInner?'primary':'grey-6'"
        flat
        dense
        size="0.8em"
        @click="canDelInner=!canDelInner"
      >
        <q-tooltip>{{canDelInner?'可以删除':'不可删除'}}</q-tooltip>
      </q-btn>
      <slot name="top-right"></slot>
      </slot>
    </div>
    <div class="kyb-select q-pa-sm" :class="(!hideToolbar?'toolbar-con':'')+(showPage?' show-page':'')">
      <div v-if="isGroup&&canAddInner" class="no-scroll q-pa-xs q-ml-md">
        <kyb-input
          class="q-ml-xs q-mr-xs float-left"
          style="width:120px"
          outlined
          clearable
          dense
          label="名称"
          v-model="newValue"
        />
        <kyb-input
          class="q-ml-xs q-mr-xs float-left"
          style="width:160px"
          completion
          outlined
          clearable
          dense
          :items="groupNamesGen()"
          label="分组"
          v-model="newGroup"
        ></kyb-input>
        <q-btn @click="add" outline dense style="height:40px;" class icon="add" color="primary"></q-btn>
      </div>
      <!-- 无数据展示 -->
      <div v-if="items.length===0 && showPage" class="column fit flex-center col">
        <q-icon name="cloud_queue" color="grey-4" size="6em" />
        <div class="text-grey-4 text-h3 q-pa-md">无数据</div>
      </div>
      <kyb-group ref="groupItems" :is-group="isGroup" :group-key="groupKey" :items="items" v-else>
        <template v-if="selectType==='more'&&isGroup" #header="{group,index}">
          <q-btn
            v-if="!showonly"
            class="float-right"
            :icon="groupSelectAllStatus[index]?'check_box':'check_box_outline_blank'"
            @click="doSelectAll(group,index)"
            dense
            flat
            size="0.9em"
            color="grey-7"
            label="选择所有"
          ></q-btn>
        </template>
        <template #default="{group,index}">
          <slot name="default" v-bind="{group,index}">
            <div v-if="group.extend" class="q-pa-xs no-scroll row wrap">
              <div v-for="(item) in group.items" :key="item[valueKey]">
                <q-btn
                  v-if="!showonly"
                  class="select-item q-ma-xs"
                  :class="(isSelect(item)?'selected bg-primary':'')"
                  :icon="isSelect(item)?'check':''"
                  @click="selectItem(item)"
                  outline
                  dense
                  v-show="!item.$isHide"
                  :label="item[titleKey]"
                >
                  <span v-if="!!showonly" v-text="item[titleKey]"></span>
                  <q-icon class="del" @click.stop="del(item)" v-if="canDelInner" name="clear"></q-icon>
                </q-btn>
                <div
                  v-if="showonly&&isSelect(item)"
                  v-text="item[titleKey]"
                  class="select-item no-select q-ma-xs"
                ></div>
              </div>

              <input
                v-if="canAddInner&&!isGroup"
                placeholder="添加新项"
                class="input q-ml-xs q-mr-xs rounded-borders"
                @keyup.enter="add"
                @keyup.esc="newValue=''"
                v-model="newValue"
              />
              <q-btn
                @click="add"
                v-if="canAddInner&&!isGroup"
                outline
                dense
                size="0.7em"
                class="item"
                icon="add"
                color="primary"
              ></q-btn>
            </div>
          </slot>
        </template>
      </kyb-group>

      <div v-if="!showonly">
        <div v-for="(v,k) in error" :key="k">
          <q-icon name="error_outline" class="text-negative q-mr-xs" size="1.2em" />
          <span v-text="v.msg" class="text-negative"></span>
        </div>
      </div>
    </div>
    <kyb-page
      v-if="showPage"
      :page-no="pageNo"
      :page-size="pageSize"
      :total-num="totalNum"
      @select-page="selectPage"
    ></kyb-page>
  </div>
</template>
<script>
import _ from 'underscore'
import { uid } from 'quasar'

import KybMdata from '../kyb-mdata.js'
export default {
  mixins: [KybMdata],
  name: 'kyb-select',
  model: {
    prop: 'value',
    event: 'input'
  },
  props: {
    isGroup: { type: Boolean, default: false },
    name: String,
    mdata: Object,
    showonly: Boolean,
    canAdd: { type: Boolean, default: true },
    canDel: { type: Boolean, default: true },
    hideToolbar: Boolean,
    showPage: Boolean,
    value: {
      type: Array,
      default: () => {
        return []
      }
    }, // 已选中的对象id
    selectType: { type: String, default: 'one' },
    titleKey: { type: String, default: 'name' }, // 显示字段
    valueKey: { type: String, default: '_id' }, // 值的字段
    groupKey: { type: String, default: 'group' }, // 分组的字段
    entityId: String,
    queryUrl: String,

    queryAuto: {
      type: Boolean,
      default: true
    },
    // 直接设置数据
    items: {
      type: Array,
      default: function() {
        return []
      }
    }
  },
  data: function() {
    return {
      selectedItem: null,
      keyword: null,
      newValue: null,
      selectedMap: {},
      newGroup: null,
      groupSelectAllStatus: {},
      canAddInner: this.canAdd,
      canDelInner: this.canDel,
      pageSize: 20,
      pageNo: 1,
      totalNum: 0
    }
  },
  watch: {
    value(obj) {
      obj || (obj = '')
      this.fixData(obj)
    }
  },
  computed: {
    error() {
      let err = {}
      if (this.mdata) {
        let minLen = this.mdata.minSelected
        if (!minLen && this.mdata.isNotNull) {
          minLen = 1
        }
        let maxLen = this.mdata.maxSelected
        let len = Object.keys(this.selectedMap).length
        if (minLen > 0 && len < minLen) {
          err.minSelected = { msg: `至少选择${minLen}项` }
        }
        if (maxLen > 0 && len > maxLen) {
          err.maxSelected = { msg: `最多选择${maxLen}项` }
        }
      }
      this.$emit('error', err)
      return err
    },
    selecteds() {
      const selecteds = []
      this.items.forEach(item => {
        let isSelected = Object.keys(this.selectedMap).findIndex(key => key === item[this.valueKey]) !== -1
        if (isSelected) {
          selecteds.push(item[this.valueKey])
        }
      })
      return selecteds
    }
  },
  async created() {
    this.fixData(this.value)
    if (this.queryAuto) {
      this.queryData()
    }
  },

  methods: {
    async queryData() {
      let isSetEntity = await this.checkModelAndEntity()
      // console.log('xxxxxx:', isSetEntity)
      if (isSetEntity) {
        let l = {}
        Object.assign(l, this.queryParam)
        let url = (this.queryUrl ? this.queryUrl : '/query') + '?1=1&'
        url += _.map(l, (v, k) => v && (encodeURIComponent(k) + '=' + encodeURIComponent(v))).filter(p => p).join('&')
        let response = await this.$axios.get(this.queryUrl ? url : await this.genBaseUrl(url))
        // 初始化
        this.pageSize = parseInt(response.data.pageSize)
        this.pageNo = parseInt(response.data.pageNo)
        this.totalNum = parseInt(response.data.totalNum)
        response.data.items.forEach(item => {
          if (this.linkMoreMyId) {
            if (this.linkMoreTable) {
              item.$selected = !!item[this.linkMoreTable + '._id']
            } else {
              item.$selected = item[this.linkEntityMyKey] === this.linkMoreMyId
            }
          }
          Object.keys(item)
            .filter(item => item.indexOf('.') > 0)
            .forEach(v => {
              let sp = v.split('.')
              if (sp[0] === this.entityInner) {
                item[sp[1]] = item[v]
                delete item[v]
              }
            })
        })
        this.items.splice(0, this.items.length, ...response.data.items)
        if (!(this.linkMoreMyId && this.selectType === 'more')) {
          this.fixSelectedData()
        }
      }
    },
    async selectPage(page) {
      Object.assign(this.queryParam, page)
      await this.queryData()
    },
    isSelect(item) {
      return this.selectedMap[item[this.valueKey]]
    },
    fixData(value) {
      // this.groupNames = this.groupNamesGen();
      // this.groupList = this.groupListGen();
      if (value) {
        // value = value.split(',')
        this.selectedMap = Array.toMap(value)
      } else {
        this.selectedMap = {}
        const isSelected = this.items.findIndex(item => item[this.valueKey] === value) !== -1
        isSelected && (this.selectedMap[value] = true)
      }

      this.fixSelectedData()
    },
    fixSelectedData() {
      this.items.forEach(item => {
        let isSelected = Object.keys(this.selectedMap).findIndex(key => key === item[this.valueKey]) !== -1
        item.$selected = isSelected
        if (isSelected) {
          if (this.selectType === 'one') {
            this.selectedItem = item
            return false
          }
        }
      })
      if (this.$refs.groupItems) {
        this.$refs.groupItems.$forceUpdate()
      }
    },
    groupNamesGen() {
      let groupMap = {}
      this.items.forEach(item => {
        let name = item[this.groupKey]
        if (name && _.isString(name) && name.length) {
          groupMap[name] = true
        }
      })
      return _.keys(groupMap)
    },

    doSelectAll(group, index) {
      console.log(group.selectAll)
      this.groupSelectAllStatus[index] = !this.groupSelectAllStatus[index]
      group.items.forEach(item => {
        this.selectItem(item, this.groupSelectAllStatus[index])
      })
      this.$refs.groupItems.$forceUpdate()
      // this.$forceUpdate();
      this.sendChange()
    },
    async selectItem(item, selected) {
      if (this.selectType === 'one') {
        if (this.selectedItem && this.selectedItem !== item) {
          this.selectedItem.$selected = false
        }
      }
      item.$selected = selected === null || selected === undefined ? !item.$selected : selected
      this.selectedItem = item
      this.$emit('selected', item)
      this.$forceUpdate()
      this.sendChange()
    },
    sendChange() {
      if (this.selectType === 'one') {
        this.selectedMap = {}
      }
      this.items.forEach(v => {
        if (v.$selected) {
          this.selectedMap[v[this.valueKey]] = true
        } else {
          delete this.selectedMap[v[this.valueKey]]
        }
      })

      this.$emit('input', _.keys(this.selectedMap))
    },
    async find(keyword) {
      this.findTimeout && clearTimeout(this.findTimeout)
      this.findTimeout = setTimeout(async () => {
        if (this.moduleInner && this.entityInner) {
          if ((keyword || keyword === 0) && keyword.length) {
            this.queryParam.___keyword_field = this.titleKey
            this.queryParam.___keyword = keyword
            this.queryParam.pageNo = 1
          } else {
            delete this.queryParam.___keyword_field
            delete this.queryParam.___keyword
          }
          await this.queryData()
        } else {
          this.items.forEach(item => {
            item.$isHide = (keyword || keyword === 0) && keyword.length && item[this.titleKey].indexOf(keyword) === -1
          })
          this.$forceUpdate()
        }
        delete this.findTimeout
      }, 100)
    },
    async add() {
      let n = {}
      n[this.titleKey] = this.newValue
      if (this.isGroup) {
        n[this.groupKey] = this.newGroup
        this.newGroup = ''
      }
      n._id = uid()
      if (this.moduleInner && this.entityInner) {
        let response = await this.$axios.post(await this.genBaseUrl('/save'), n)
        this.newValue = ''
        this.items.push(response.data)
      } else {
        this.newValue = ''
        this.items.push(n)
      }
    },
    del(item) {
      this.$q.showConfirm('是否删除该项!', async () => {
        let index = this.items.indexOf(item)
        this.items.splice(index, 1)
      })
    }
  }
}
</script>
<style lang="stylus">
.kyb-select-con{
  padding:0;
}
.kyb-select-con .input {
  width: 90px;
  border: 1px solid #ccc;
  padding: 2px 6px;
}

.kyb-select.toolbar-con {
  position: relative;
}

.kyb-select.show-page {
  position: relative;
}

.kyb-select-con .page-con {
  position: sticky;
  position: -webkit-sticky;
  bottom: 0;
  left: 0;
  right: 0;
  border-top: 1px solid $grey-4;
  background: $grey-3;
  min-height: 36px;
  overflow: hidden;
  white-space: nowrap;
  margin: 0;
}

.kyb-select-con .toolbar {
  border-bottom: 1px solid $grey-4;
  background: $grey-3;
  height: auto;
  position: sticky;
  position: -webkit-sticky;
  top: 0;
  left: 0;
  right: 0;
  overflow: hidden;
  z-index:1;
}

.kyb-select .select-item {
  border-radius: 15px;
  color: $grey-9;
  padding: 1px 6px;
  transition: all 0.5s;
}

.kyb-select .select-item.no-select {
  display: inline-block;
  padding: 4px 6px;
  font-size: 1.08em;
  border-radius: 15px;
  border: 1px solid $grey-4;
}

.kyb-select .select-item.selected {
  color: white;
}

.kyb-select .select-item.no-select .del {
  font-size: 1.3em;
  cursor: pointer;
}

.kyb-select .select-item .del:hover {
  color: red;
}
</style>
