<!--
 * @Description: In User Settings Edit
 * @Author: your name
 * @Date: 2019-09-05 22:29:51
 * @LastEditTime: 2019-11-25 13:58:54
 * @LastEditors: Please set LastEditors
 -->
<template>
  <el-dialog
    ref="tpicker"
    class="table-picker"
    v-dialogDrag
    :title="title"
    :visible.sync="dialogVisible"
    :before-close="handleClose"
    append-to-body
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :width="mutiFlag ? '90%' : '50%'"
    top='1%'
  >
    <div class="my-favorites" v-if="tableData.length && isFavorite">
      <div class="title">我的收藏</div>
      <div class="favorite-list" ref="favoriteList">
        <el-tag
          v-for="row of tableData.filter((row, index) => favoriteShow || index < maxShowTag)"
          :key="row[realKey]"
          type="info"
          size="medium"
          closable
          @click="handlerPick(row)"
          @close="switchFavorites(row, 'delete')"
        >
          {{ row[realName] }}
        </el-tag>
        <el-button
          ref="switchButton"
          type="primary"
          size="mini"
          :icon="favoriteShow ? 'el-icon-d-arrow-right' : 'el-icon-d-arrow-left'"
          @click="favoriteShow = !favoriteShow"
        >
        </el-button>
      </div>
    </div>
    <template v-if="mutiFlag && tableColumn.length">
      <lov-table
        class="muti-select-table"
        index-style="selection"
        height="300px"
        :autoSearch="autoSearch"
        :search-info="searchInfo"
        :table-column="tableColumn"
        :request-url="url"
        :params="keyObj"
        :is-remenber="true"
        :checked-row.sync="selection"
        :page-size="5"
        :page-sizes="pageSizes"
        :row-key="realKey">
        <template slot="favorites" slot-scope="{ row }">
          <i class="favorite el-icon-star-on" @click.stop="switchFavorites(row, 'delete')" v-if="favoriteList.includes(row[realKey])"></i>
          <i class="favorite el-icon-star-off" @click.stop="switchFavorites(row, 'add')" v-else></i>
        </template>
        <list-table
          slot='picked'
          class="muti-list-table"
          height="300px"
          :table-column="tableColumn.filter(({ code }) => code !== 'favorites')"
          :selected="selection"
          :row-key="realKey"
          :default-value="defaultValue"
          :is-default="isDefault"
          @set-default="handlerSetDefault"
          @selectChange="selectChange"
        >
        </list-table>
      </lov-table>
    </template>
    <zte-table
      v-else-if="tableColumn.length"
      :autoSearch="autoSearch"
      :search-info="searchInfo"
      :table-column="tableColumn"
      :request-url="url"
      :params='keyObj'
      :page-size="5"
      :page-sizes="pageSizes"
      :row-key="realKey"
      @row-select="handlerSelect"
      @dblclick="handlerPick">
      <template slot="favorites" slot-scope="{ row }">
        <i class="favorite el-icon-star-on" @click="switchFavorites(row, 'delete')" v-if="favoriteList.includes(row[realKey])"></i>
        <i class="favorite el-icon-star-off" @click="switchFavorites(row, 'add')" v-else></i>
      </template>
    </zte-table>
    <div v-else v-loading="loading" style="text-align: center;">{{ $t('el.table.emptyText') }}</div>
    <span slot="footer" class="dialog-footer">
      <el-button size="small" @click="closeDialog">{{ $t('关闭') }}</el-button>
      <Throttle :time="1000" events="click">
        <el-button size="small" type="primary" @click.native="handleSubmit">{{ $t('提交') }}</el-button>
      </Throttle>
    </span>
  </el-dialog>
</template>

<script>
import qs from 'qs';
import lovTable from './lov-table';
import listTable from './list-table';
import zteTable from './zte-table';

export default {
  name: 'tablePicker',
  components: {
    listTable,
    lovTable,
    zteTable,
  },
  props: {
    dialogVisible: {
      type: Boolean,
      required: true,
      default: false,
    },
    service: {
      type: String,
      default: 'base',
    },
    tableKey: {
      type: String,
      required: true, // 'boe.user.by.le_id'
    },
    rowKey: {
      type: String,
      required: true,
    },
    rowName: String,
    title: {
      type: String,
    },
    selected: {
      type: [String, Array],
    },
    isCache: {
      type: Boolean,
      default: true,
    },
    rowTrans: Array,
    rowExtends: {
      type: Array,
      default: () => ([]),
    },
    params: {
      type: Object,
      default: () => null,
    },
    config: Object,
    requestUrl: String,
    defaultValue: String,
    isDefault: Boolean,
    pageSizes: {
      type: Array,
      default: () => ([5, 10, 20]),
    },
  },
  data() {
    return {
      mutiFlag: false,
      searchInfo: [],
      tableColumn: [],
      tableData: [],
      cache: [],
      singleSelected: [],
      selection: [],
      autoSearch: false,
      isFavorite: true,
      loading: true,
      pathKey: this.$route.meta.menuId || `${window.location.pathname}#${this.$route.path}`,
      favoriteList: [],
      favoriteShow: false,
      maxShowTag: 0,
    };
  },
  computed: {
    keyObj() {
      let keyObj = { lovKey: this.tableKey };
      if (this.params) {
        keyObj = Object.assign(keyObj, this.params);
      }
      return keyObj;
    },
    realKey() {
      if (this.rowTrans) {
        for (let i = 0; i < this.rowTrans.length; i++) {
          if (this.rowTrans[i].to === this.rowKey) {
            return this.rowTrans[i].from;
          }
        }
      }
      return this.rowKey;
    },
    realName() {
      if (this.rowTrans) {
        for (let i = 0; i < this.rowTrans.length; i++) {
          if (this.rowTrans[i].to === this.rowName) {
            return this.rowTrans[i].from;
          }
        }
      }
      return this.rowName;
    },
    selectionParms() {
      let obj = {
        page: 1,
        limit: 9999,
        lovKey: this.tableKey,
      };
      if (this.params) {
        obj = Object.assign(obj, this.params);
      }
      return obj;
    },
    url() {
      return this.requestUrl || `/${this.service}/lov/findDatas`;
    },
    key() {
      const key = `${this.pathKey}&${this.tableKey || this.requestUrl}`;
      return key;
    },
  },
  watch: {
    selected() {
      this.initSelection();
    },
    favoriteList(val) {
      if (val && val.length) {
        this.initFavorite();
      } else {
        this.tableData = [];
      }
    },
  },
  methods: {
    /**
     * @augments
     * data 需要转换的数据
     * transRule 转换规则
     * ex: {
     *       to: 'code',
     *       from: 'USER_CODE',
     *     }
     */
    transferData(data, transRule) {
      let finalData = [];
      if (data.length) {
        if (transRule) {
          finalData = data.map((item) => {
            let newItem = {};
            if (transRule.length || this.rowExtends.length) {
              transRule.forEach((rule) => {
                newItem[rule.to] = item[rule.from];
              });
              (this.rowExtends || []).forEach((extend) => {
                newItem[extend.from] = item[extend.from];// 扩展属性需要保留传递出去
              }); 
            } else {
              newItem = JSON.parse(JSON.stringify(item));
            }
            return newItem;
          });
        } else {
          finalData = data;
        }
      }
      return finalData;
    },
    async initSelection() {
      if (this.selected) {
        if (this.mutiFlag) {
          const params = {
            ...this.selectionParms,
            [this.realKey]: this.selected,
          }
          await this.$http.post(this.url, qs.stringify(params)).then(
            (res) => {
              this.selection = res.data.page.list || [];
            }).catch(() => {});
        } else {
          this.selection = this.selected;
        }
      }
    },
    initFavorite() {
      const params = {
        ...this.selectionParms,
        favoritesKey: this.favoriteList.join('^'),
      };
      this.$http.post(this.url, qs.stringify(params))
        .then(
          ({ data }) => {
            const list = data.page && data.page.list || [];
            this.tableData = list.sort((firstEl, secondEl) => this.favoriteList.indexOf(firstEl[this.realKey]) - this.favoriteList.indexOf(secondEl[this.realKey]))
            this.maxShowTag = this.tableData.length;
            this.$nextTick(() => {
              this.computeTagCount();
            })
          })
        .catch();
    },
    computeTagCount() {
      const switchButton = this.$refs.switchButton.$el;
      const favoriteList = this.$refs.favoriteList;
      const maxWidth = favoriteList.clientWidth - switchButton.clientWidth;
      const tags = favoriteList.getElementsByClassName('el-tag');

      let totalWidth = 0;
      let totalIndex = 0;
      for (const tag of tags) {
        const offsetWidth = tag.offsetWidth;
        const marginRight = parseFloat(getComputedStyle(tag).marginRight);
        const width = offsetWidth + marginRight;
        if (totalWidth + width > maxWidth) {
          break;
        }
        totalWidth += width;
        totalIndex++;
      }
      this.maxShowTag = totalIndex;
    },
    handleClose() {
      this.$emit('update:dialogVisible', false);
    },
    handlerSelect(row) {
      if (row) {
        this.singleSelected = [row];
      } else {
        this.singleSelected = [];
      }
    },
    handlerPick(row) {
      if (this.mutiFlag) {
        const index = this.selection.findIndex(selected => selected[this.realKey] === row[this.realKey]);
        if (index === -1) {
          this.selection.push(row);
        }
      } else {
        this.handlerSelect(row);
        this.handleSubmit();
      }
    },
    handleSubmit() {
      if (this.mutiFlag) {
        this.$emit('selectChange', this.transferData(this.selection, this.rowTrans));
      } else {
        if (!this.singleSelected.length) {
          this.$message.warning('请选择一条数据');
          return;
        }
        this.$emit('singleSelectChange', this.transferData(this.singleSelected, this.rowTrans));
      }
      this.closeDialog();
    },
    closeDialog() {
      this.$emit('update:dialogVisible', false);
    },
    selectChange(index) {
      if (index || index === 0) {
        this.selection.splice(index, 1);
      } else {
        this.selection = [];
      }
    },
    setConfig(config) {
      this.mutiFlag = config.singleGrid !== 'Y';
      this.autoSearch = config.autoQuery === 'Y';
      this.isFavorite = process.env.VUE_APP_TABLE_PICKER_FAVORITE !== 'N' && config.isShowFavorites !== 'N';
    
      if (this.isFavorite) {
        this.getFavorites();
      }
      
      this.searchInfo = config.query;
      const favorCol = this.isFavorite ? [
        {
          label: '收藏',
          code: 'favorites',
          temp: 'favorites',
          width: 50,
        },
      ] : [];
      this.tableColumn = config.field.concat(favorCol);
    },
    handlerSetDefault(value) {
      this.$emit('update:defaultValue', value);
    },
    getFavorites() {
      const params = {
        key: this.key,
      };
      this.$http.post('base/favorites/get', this.$qs.stringify(params))
        .then(
          ({ data }) => {
            const list = data.data || [];
            this.favoriteList = list.map(({ value }) => value);
          }
        )
        .catch();
    },
    switchFavorites(row, flag) {
      const value = row[this.realKey];
      const params = {
        key: this.key,
        value,
      };
      const flagObj = {
        add: '收藏',
        delete: '取消收藏',
      };
      this.$http.post('base/favorites/' + flag, this.$qs.stringify(params))
        .then(
          () => {
            this.$message.success(`${flagObj[flag]}成功`);
            const index = this.favoriteList.indexOf(value);
            if (flag === 'add' && index === -1) {
              this.favoriteList.push(value);
            } else if (flag === 'delete' && index > -1) {
              this.favoriteList.splice(index, 1);
            }
          },
        )
        .catch(
          () => {
            this.$message.error(`${flagObj[flag]}失败`);
          }
        );
    },
  },
  async created() {
    if (!this.config) {
      await this.$http.get(`/${this.service}/lov/getLovConfig?lovKey=${this.tableKey}`).then(
        (res) => {
          res = res.data;
          this.setConfig(res.data);
        },
      ).catch(() => { });
    } else {
      this.setConfig(this.config);
    }
    await this.initSelection();
    this.loading = false;
  },
};
</script>
