<template>
  <div style="display: contents">
    <template>
      <Col v-for="(column, index) in columns" :key="index" v-bind="getGrid(column.columnWidth)">
        <template v-if="column.isShow">
          <div :key="column.code" v-if="column.controlType === 'Placeholder'"></div>
          <FormItem :label="getNameI18n(column)" :key="column.code" v-if="column.controlType !== 'Placeholder'">
            <template v-if="column.controlType === 'Custom'">
              <!--
                  @slot 自定义列
                  @binding {object} filter 数据对象
                  @binding {object} column 列对象
                  @binding {string} code 列代码
              -->
              <slot name="column" :filter="data" :column="column" :code="column.code"></slot>
            </template>
            <template v-else-if="column.controlType === 'Label'">
              <div v-html="showData(data, column)"></div>
            </template>
            <template v-else-if="column.controlType === 'TextInput'">
              <Input
                size="small"
                type="text"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                @on-keyup="$event => onKeyup($event)"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
              />
            </template>
            <template v-else-if="column.controlType === 'NumberInput'">
              <Input
                size="small"
                type="number"
                number
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                @on-keyup="$event => onKeyup($event)"
                :style="{ width: column.controlWidth == null ? '100px' : column.controlWidth + 'px' }"
                :placeholder="column.description"
              />
            </template>
            <template v-else-if="column.controlType === 'Select'">
              <Select
                size="small"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                clearable
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              >
                <Option v-for="item in getDataSource(data, column)" :key="item.id" :value="item.id">{{ item.name }}</Option>
              </Select>
            </template>
            <template v-else-if="column.controlType === 'MultiSelect'">
              <Select
                size="small"
                :value="parseArrayFilterData(data, column)"
                :multiple="true"
                clearable
                @input="$event => setArrayFilterData(data, column, $event)"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              >
                <Option v-for="item in getDataSource(data, column)" :key="item.id" :value="item.id">{{ item.name }}</Option>
              </Select>
            </template>
            <template v-else-if="column.controlType === 'TreeSelect'">
              <TreeSelect
                size="small"
                :value="parseTreeFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                :data="getDataSource(data, column)"
                :clearable="true"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              ></TreeSelect>
            </template>
            <template v-else-if="column.controlType === 'MultiTreeSelect'">
              <TreeSelect
                size="small"
                :value="parseArrayFilterData(data, column)"
                @input="$event => setArrayFilterData(data, column, $event)"
                :data="getDataSource(data, column)"
                :multiple="true"
                :show-checkbox="true"
                :clearable="true"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              ></TreeSelect>
            </template>
            <template v-else-if="column.controlType === 'SelectWithOther'">
              <Select
                size="small"
                :value="parseFilterDataWithOther(data, column)"
                @input="$event => setFilterDataWithOther(data, column, $event)"
                clearable
                :style="{ width: column.controlWidth == null ? '40%' : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              >
                <Option v-for="item in getDataSource(data, column)" :key="item.id" :value="item.id">{{ item.name }}</Option>
                <Option key="__Other" value="__Other">{{ $t('Front_Label_Others') }}</Option>
              </Select>
              <Input
                type="text"
                size="small"
                v-show="parseFilterDataWithOther(data, column) == '__Other'"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                :style="{ width: column.controlWidth == null ? '40%' : column.controlWidth + 'px' }"
                style="margin-left: 4px"
                :maxlength="column.maxLength"
                :placeholder="column.description"
                @on-change="onDataChange(column)"
              />
            </template>
            <template v-else-if="column.controlType === 'ComboSelect'">
              <Select
                size="small"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                clearable
                filterable
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                :placeholder="column.description"
                :transfer="true"
                @on-change="selected => onSelectDataChange(column, selected)"
              >
                <Option v-for="item in getDataSource(data, column)" :key="item.id" :value="item.id">{{ item.name }}</Option>
              </Select>
            </template>
            <template v-else-if="column.controlType === 'DialogSelect'">
              <dialog-select
                size="small"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                :source="column.source"
                :source-data-code="column.sourceDataCode"
                :source-display-code="column.sourceDisplayCode"
                :param="getParam(data, column)"
                :controlWidth="column.controlWidth"
                @on-change="selected => onSelectDataChange(column, selected)"
              ></dialog-select>
            </template>
            <template
              v-else-if="
                column.controlType === 'Date' ||
                column.controlType === 'DateTime' ||
                column.controlType === 'Year' ||
                column.controlType === 'Month' ||
                column.controlType === 'DateRange'
              "
            >
              <DatePicker
                size="small"
                :type="column.controlType.toLowerCase()"
                :value="parseFilterData(data, column)"
                :placeholder="column.description"
                :transfer="true"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                @on-change="
                  time => {
                    setFilterData(data, column, time);
                    onDataChange(column);
                  }
                "
              ></DatePicker>
            </template>
            <template v-else-if="column.controlType === 'Time'">
              <TimePicker
                size="small"
                type="time"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                :placeholder="column.description"
                :transfer="true"
                :style="{ width: column.controlWidth == null ? null : column.controlWidth + 'px' }"
                @on-change="onDataChange(column)"
              ></TimePicker>
            </template>
            <template v-else-if="column.controlType === 'Check'">
              <Checkbox
                size="small"
                style="line-height: 26px"
                :value="!!parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                @on-change="onDataChange(column)"
              />
            </template>
            <template v-else-if="column.controlType === 'Switch'">
              <div style="line-height: 24px">
                <Switch size="small" :value="!!parseFilterData(data, column)" @input="$event => setFilterData(data, column, $event)" @on-change="onDataChange(column)" />
              </div>
            </template>
            <template v-else-if="column.controlType === 'Radio'">
              <RadioGroup
                size="small"
                style="line-height: 22px"
                :value="parseFilterData(data, column)"
                @input="$event => setFilterData(data, column, $event)"
                @on-change="selected => onSelectDataChange(column, selected)"
              >
                <Radio v-for="item in getDataSource(data, column)" :key="item.id" :label="item.id">
                  <span>{{ item.name }}</span>
                </Radio>
              </RadioGroup>
            </template>
            <template v-else>{{ $t('Front_Label_Control_Type_Not_Supported') }} {{ column.controlType }}</template>
          </FormItem>
        </template>
      </Col>
      <Col v-if="tableView.keywordEnable" v-bind="grid6">
        <FormItem :label="$t('Front_Label_Keyword')">
          <Input v-model="data.keyword" v-focus @on-keyup="$event => onKeyup($event)" size="small" />
        </FormItem>
      </Col>
    </template>
  </div>
</template>
<script>
  import mixinPage from '../../mixins/page';
  import mixin from './mixin';
  import modelApi from '../../api/model';
  import customModelApi from '../../api/customModel';
  import DialogSelect from '../input/dialog-select.vue';
  import dateFormat from 'date-fns/format';

  export default {
    mixins: [mixin, mixinPage],
    components: { DialogSelect },
    data() {
      return {};
    },
    async created() {
      this.init();
    },
    props: {
      // 表格视图
      tableView: {
        type: Object
      },
      // 筛选项数据
      data: {
        type: Object
      },
      // 字段
      columns: {
        type: Array
      }
    },
    watch: {
      columns() {
        this.init();
      }
    },
    computed: {},
    methods: {
      init() {
        let data = this.data;
        this.columns.forEach(item => {
          if (item.defaultValue) {
            if (item.defaultValue == '{today}') {
              // 当前日期
              let date = new Date();
              let value = date.toISOString().replace(/T.*/, '');
              this.setFilterData(data, item, new Date(value));
            } else if (item.defaultValue.startsWith('{today(') && item.defaultValue.endsWith(')}')) {
              // 当前时间转字符串
              let format = item.defaultValue.substr(7, item.defaultValue.length - 9);
              this.setFilterData(data, item, dateFormat(new Date(), format));
            } else if (item.defaultValue == '{currentUserID}') {
              // 当前用户编号
              this.setFilterData(data, item, this.info.id);
            } else if (item.defaultValue == '{currentUser}') {
              // 当前用户姓名
              this.setFilterData(data, item, this.info.name);
            } else {
              if (item.dataType === 'Integer') {
                this.setFilterData(data, item, parseInt(item.defaultValue));
              } else if (item.dataType === 'Decimal') {
                this.setFilterData(data, item, parseFloat(item.defaultValue));
              } else if (item.dataType === 'Boolean' && item.defaultValue.toUpperCase == 'TRUE') {
                this.setFilterData(data, item, true);
              } else if (item.dataType === 'Boolean' && item.defaultValue.toUpperCase == 'FALSE') {
                this.setFilterData(data, item, false);
              } else {
                this.setFilterData(data, item, item.defaultValue);
              }
            }
          }
        });

        // 初始化触发规则
        setTimeout(() => {
          // 初始化静态选项
          this.initStaticItem();

          // 初始化触发规则
          this.initTrigger();

          this.onDataChange();
        });
      },
      // 初始化静态选项
      initStaticItem() {
        this.columns.forEach(column => {
          if (column.isStaticItem) {
            column.dataSource = [];

            if (!!(column.itemData || '').trim()) {
              column.itemData.split(/[\n]/).forEach(item => {
                if (!!(item || '').trim()) {
                  if (item.split(':').length > 1) {
                    let key = item.split(':')[0];
                    let value = item.split(':')[1];

                    column.dataSource.push({
                      id: key,
                      name: value
                    });
                  } else {
                    column.dataSource.push({
                      id: item,
                      name: item
                    });
                  }
                }
              });
            }
          }
        });

        this.$forceUpdate();
      },
      // 初始化触发规则
      initTrigger() {
        // 触发规则
        this.columns.forEach(column => {
          column.triggers = [];
        });

        this.columns
          .filter(column => {
            return !column.isStaticItem && !!(column.source || '').trim() && !!(column.param || '').trim();
          })
          .forEach(column => {
            let param = JSON.parse(column.param);
            for (let key in param) {
              this.columns
                .filter(item => {
                  return param[key] === item.code;
                })
                .forEach(item => {
                  item.triggers.push(column);
                });
            }
          });
      },
      // 填充数据源
      async fillDataSource(data, column, param) {
        // 参数完整，查询数据
        let res;
        if (column.isSourceCustom) {
          res = await customModelApi.query(column.source, param);
        } else {
          res = await modelApi.query(column.source, param);
        }

        column.rawData = res.data;

        if (column.controlType === 'TreeSelect' || column.controlType === 'MultiTreeSelect') {
          let data = res.data.map(item => {
            return {
              id: !(column.sourceDataCode || '').trim() ? item.id : this.parseData(item, column.sourceDataCode),
              name: this.parseData(item, column.sourceDisplayCode),
              parentID: item.parentID
            };
          });

          column.dataSource = this.getTreeDataSource(data, column, null);
        } else {
          column.dataSource = res.data.map(item => {
            return {
              id: !(column.sourceDataCode || '').trim() ? item.id : this.parseData(item, column.sourceDataCode),
              name: this.parseData(item, column.sourceDisplayCode)
            };
          });

          // 默认第一项
          if (data) {
            if (this.parseFilterData(data, column) == null && column.isDefaultFirst && res.length > 0) {
              this.setData(data, column.code, this.parseData(res[0], column.sourceDataCode));
            }
          }
        }

        this.$forceUpdate();

        // 更新data触发刷新
        // this.data = { ...this.data };

        // 触发
        this.onDataChange(column);
      },
      // 获取树结构数据源
      getTreeDataSource(data, column, parentID) {
        let result = data
          .filter(item => {
            return item.parentID == parentID;
          })
          .map(item => {
            return {
              value: !(column.sourceDataCode || '').trim() ? item.id : this.parseData(item, column.sourceDataCode),
              title: this.parseData(item, column.sourceDisplayCode),
              selected: false,
              checked: false
            };
          });

        if (result.length > 0) {
          for (let item of result) {
            item.expand = true;
            item.children = this.getTreeDataSource(data, column, item.value);
          }
        }

        return result;
      },
      // 获取数据源
      getDataSource(data, column) {
        if (!column.isStaticItem && column.dataType.indexOf('Enum:') === 0) {
          // 枚举
          return this.getEnumList(column.dataType.split(':')[1]);
        } else {
          return column.dataSource == null ? [] : column.dataSource;
        }
      },
      // // 可筛选下拉框加载数据
      // loadOption(data, column, keyword) {
      //     let param = this.getParam(data, column);

      //     if (param != null) {
      //         if (!(keyword || '').trim() && this.parseFilterData(data, column) != null) {
      //             param.id = this.parseFilterData(data, column);
      //         } else {
      //             param.keyword = keyword;
      //         }
      //         param.per = 20;

      //         this.fillDataSource(data, column, param);
      //     } else {
      //         // 参数不完整，清空数据
      //         column.dataSource = [];
      //         this.setData(data, column.code, null);
      //         // column.displayValue = null;

      //         // 触发
      //         column.triggers.forEach(item => {
      //             item.needRefresh = true;
      //         });
      //     }
      // },
      // 选项变化事件
      onSelectDataChange(sender, selected) {
        let code;
        if (sender.code.endsWith('ID')) {
          code = sender.code.substr(0, sender.code.length - 2);
        }
        let model = null;
        if (typeof selected == 'object') {
          if (selected instanceof Array) {
            model = [];

            for (let item of selected) {
              if (typeof item == 'object') {
                model.push(item);
              } else {
                if (sender.rawData) {
                  model.push(
                    sender.rawData.find(rawData => {
                      return this.parseFilterData(rawData, sender.sourceDataCode) == item;
                    })
                  );
                } else {
                  model.push(item);
                }
              }
            }
          } else {
            model = selected;
          }
        } else {
          if (sender.rawData) {
            model = sender.rawData.find(rawData => {
              return this.parseFilterData(rawData, sender.sourceDataCode) == selected;
            });
          } else {
            model = selected;
          }
        }

        if (code) {
          this.setData(this.data, code, model);
        }

        this.onDataChange(sender, model);
      },
      // 数据变化事件
      onDataChange(sender, selected) {
        setTimeout(() => {
          this.$emit('on-change', sender, selected);
        });

        // 计算需要刷新的字段
        if (sender == null || sender.triggers !== []) {
          this.columns.forEach(function (column) {
            if (
              !column.isStaticItem &&
              !!(column.source || '').trim() &&
              (sender == null ||
                sender.triggers.some(item => {
                  return item.id === column.id;
                }))
            ) {
              column.needRefresh = true;
            }
          });
        }

        // 刷新数据源
        while (true) {
          let column = this.columns.filter(item => {
            return item.needRefresh === true;
          })[0];

          if (column == null) {
            // 没有需要刷新的字段
            break;
          }

          let param = this.getParam(this.data, column);

          if (
            column.controlType === 'Select' ||
            column.controlType === 'MultiSelect' ||
            column.controlType === 'TreeSelect' ||
            column.controlType === 'MultiTreeSelect' ||
            column.controlType === 'SelectWithOther' ||
            column.controlType === 'ComboSelect' ||
            column.controlType === 'Radio'
          ) {
            // 选择框、单选框组
            if (param != null) {
              this.fillDataSource(this.data, column, param);
            } else {
              // 参数不完整，清空数据
              column.dataSource = [];
              this.setData(this.data, column.code, null);
              // column.displayValue = null;

              // 触发
              column.triggers.forEach(item => {
                item.needRefresh = true;
              });
            }
          }

          column.needRefresh = false;
        }

        this.$forceUpdate();
      },
      // 筛选项取值
      parseFilterData(model, column) {
        return model[this.getFilterKey(column)];
      },
      // 筛选项赋值
      setFilterData(model, column, value) {
        model[this.getFilterKey(column)] = value;

        if (column.code.indexOf('.') >= 0) {
          this.setData(model, column.code, value);
        }
      },
      // 筛选项取值(数组)
      parseArrayFilterData(model, column) {
        let data = [];
        let value = this.parseFilterData(model, column);
        if (value != null && value != '') {
          data = value.split(',');
        }

        return data;
      },
      // 筛选项赋值(数组)
      setArrayFilterData(model, column, value) {
        let data = '';
        if (value != null) {
          data = value.join(',');
        }

        this.setFilterData(model, column, data);
      },
      // 根据表达式取值（带其他）
      parseFilterDataWithOther(model, column) {
        let expression = column.code;
        let selectValue = this.parseData(model, expression + '_o');

        let value = this.parseFilterData(model, expression);
        let dataSource = this.getDataSource(model, column);

        if (selectValue != null) {
          return selectValue;
        } else if (value == null) {
          return null;
        } else if (
          dataSource &&
          dataSource.some(item => {
            return item.id == value;
          })
        ) {
          return value;
        } else {
          return '__Other';
        }
      },
      // 根据表达式赋值（带其他）
      setFilterDataWithOther(model, column, value) {
        this.setData(model, column.code + '_o', value);
        if (value != '__Other') {
          this.setFilterData(model, column, value);
        } else {
          this.setFilterData(model, column, null);
        }
      },
      // 获取筛选项Key
      getFilterKey(column) {
        let key = column.code;

        //if (!this.isDataSource) {
        switch (column.controlType) {
          case 'Date':
            key = 'd_' + key; // 日
            break;
          case 'Month':
            key = 'm_' + key; // 月
            break;
          case 'Year':
            key = 'y_' + key; // 年
            break;
        }
        //}

        switch (column.operator) {
          case 'GreaterThan':
            key = key + '_g'; // 大于
            break;
          case 'LessThan':
            key = key + '_l'; // 小于
            break;
          case 'GreaterThanOrEqual':
            key = key + '_ge'; // 大于等于
            break;
          case 'LessThanOrEqual':
            key = key + '_le'; // 小于等于
            break;
          case 'NotEqual':
            key = key + '_n'; // 不等于
            break;
          case 'Contains':
            key = key + '_c'; // 模糊匹配
            break;
        }

        return key;
      },
      // 键盘事件
      onKeyup(e) {
        this.$emit('on-keyup', e);
      },
      // 根据表达式取值（树）
      parseTreeFilterData(data, column) {
        let value = this.parseFilterData(data, column);

        if (value == null) {
          return '';
        } else {
          return value;
        }
      },
      // 获取多语言名称
      getNameI18n(column) {
        if (this.layout.showI18n) {
          if (column.code) {
            let key = 'DataView_' + this.tableView.code + '_Filter_' + column.code + '_' + column.operator;
            let text = this.$t(key);
            if (text == key) {
              return column.name;
            } else {
              return text;
            }
          }
        } else {
          return column.name;
        }
      }
    }
  };
</script>
