<template>
  <div class="filter-box" :class="{ multiple }">
    <el-input v-if="!multiple" placeholder="请输入内容" class="input-with-select" :clearable="true" size="mini" v-model="filterData.value">
      <el-select class="prepend" slot="prepend" placeholder="请选择" v-model="filterData.name" @clear="handleClear" clearable>
        <el-option v-for="(item, index) in fields" :label="item.field.label" :value="item.field.name" :key="'filter' + index"></el-option>
      </el-select>
      <el-button slot="append" icon="el-icon-search" @click="query"></el-button>
    </el-input>
    <el-form v-else ref="form" :model="form" :inline="true">
      <el-form-item v-for="(item, index) in simpleFields" :key="'form-field-' + index" :label="item.field.label">
        <naf-input v-model="form[item.field.name]" size="mini" :dict="item.dict" :clearable="true"></naf-input>
      </el-form-item>
      <el-form-item>
        <el-dropdown v-if="matcher == 'all'" size="mini" split-button type="primary" @click="query" @command="handleCommand">
          查询
          <el-dropdown-menu slot="dropdown">
            <el-dropdown-item command="exact">精确查询<i v-if="matching == 'exact'" class="el-icon-check el-icon--right"></i></el-dropdown-item>
            <el-dropdown-item command="like">模糊查询<i v-if="matching == 'like'" class="el-icon-check el-icon--right"></i></el-dropdown-item>
          </el-dropdown-menu>
        </el-dropdown>
        <el-button v-else type="primary" size="mini" @click="query">查询</el-button>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" size="mini" @click="reset">重置</el-button>
      </el-form-item>
      <el-form-item v-if="$scopedSlots.ext || moreFields.length > 0">
        <el-button type="primary" size="mini" @click="toggleMore" v-if="!showMore">更多</el-button>
        <el-button type="default" size="mini" @click="toggleMore" v-else>收起</el-button>
      </el-form-item>
    </el-form>
    <slot name="ext" v-bind="{ form, handleFieldChange }" v-if="showMore">
      <el-form ref="form-ext" :model="form" :inline="true">
        <el-form-item v-for="(item, index) in moreFields" :key="'form-ex-field-' + index" :label="item.field.label">
          <naf-input v-model="form[item.field.name]" size="mini" :dict="item.dict" :clearable="true"></naf-input>
        </el-form-item>
      </el-form>
    </slot>
  </div>
</template>

<script>
import NafInput from './naf-input';
import { Util } from 'naf-core';

const defaultMatcher = process.env.VUE_APP_FILTER_MATCHER_DEFAULT || 'like';

export default {
  components: {
    NafInput,
  },
  props: {
    fields: { type: Array, required: true },
    multiple: { type: Boolean, default: eval(process.env.VUE_APP_FILTER_MULTI || false) },
    matcher: { type: String, default: process.env.VUE_APP_FILTER_MATCHER || 'like' },
    maxFields: { type: Number, default: 4 },
  },
  data() {
    return {
      filterData: { name: '', value: '' },
      form: {},
      matching: (defaultMatcher == 'exact' && 'exact') || (defaultMatcher == 'like' && 'like') || 'like',
      showMore: false,
    };
  },
  methods: {
    async query() {
      const filter = { ...this.filter, exact: this.matching != 'like' };
      const paging = { page: this.page, size: this.size };
      Object.freeze(filter);
      Object.freeze(paging);
      this.$emit('query', {
        filter,
        paging,
      });
    },
    handleClear() {
      this.filterData = { name: '', value: '' };
    },
    reset() {
      this.form = {};
      this.query();
    },
    handleCommand(command) {
      this.matching = command;
      this.query();
    },
    toggleMore() {
      this.showMore = !this.showMore;
    },
    handleFieldChange(name, value) {
      console.debug(`filter field ${name} changed:`, value);
      this.$set(this.form, name, value);
    },
  },
  computed: {
    filterFields() {
      return this.fields.map(p => ({
        ...p,
        dict: p.dict || (this.$dict && p.formatter && p.formatter.name === 'dict' && this.$dict(p.formatter.param)),
      }));
    },
    filter() {
      if (this.multiple) {
        const entries = Object.entries(this.form).filter(p => p[1] != undefined && p[1] != null && p[1] != '');
        return Object.fromEntries(entries);
      }
      let filter = { [this.filterData.name]: this.filterData.value };
      if (this.filterData.name == undefined || this.filterData.value == undefined || this.filterData.value == '') {
        filter = undefined;
      }
      return filter;
    },
    simpleFields() {
      return this.filterFields.slice(0, this.maxFields);
    },
    moreFields() {
      return this.filterFields.slice(this.maxFields) || [];
    },
  },
};
</script>

<style lang="less" scoped>
.filter-box {
  width: 300px;
  display: inline-block;
  margin-right: 20px;
  .prepend.el-select {
    width: 100px;
  }
}
.filter-box.multiple {
  width: 100%;
  min-width: 920px;
  .naf-input {
    width: 100px;
    /deep/ .el-input__inner {
      padding: 0 5px;
    }
  }
  .el-form-item {
    margin-bottom: 0;
  }
}
</style>
