<template>
  <div>
    <el-dialog
      append-to-body
      title="数据集权限过滤器"
      :visible.sync="show"
      custom-class="dataset-global-filter"
      width="500px"
      @close="$emit('change', false)"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <el-dropdown @command="onAddFilter" trigger="click">
        <el-button type="success" size="mini" plain icon="el-icon-plus" style="margin: 0 10px">添加</el-button>
        <el-dropdown-menu slot="dropdown" class="newbi-dataset-filter-drop">
          <el-input v-model="searchKey" placeholder="筛选" clearable></el-input>
          <div class="fields">
            <el-dropdown-item v-for="(field, i) of searchedFields" :key="i" :command="field" :class="[field.dimensionType]">
              {{ field.columnTitle }}
            </el-dropdown-item>
          </div>
        </el-dropdown-menu>
      </el-dropdown>
      <global-filter-node :node="filter.filterRelation.where" :level="1"></global-filter-node>
      <div class="dialog-btns">
        <el-button size="small" @click="$emit('change', false)">取消</el-button>
        <el-button size="small" type="primary" @click="setJson">确定</el-button>
      </div>
    </el-dialog>
    <!-- 过滤器编辑框 -->
    <el-dialog append-to-body :visible.sync="showCondition" title="编辑过滤器" custom-class="bigdata-filter" width="660px">
      <div v-if="nowCondition">
        <el-form size="mini" label-width="80px">
          <el-form-item label="当前字段">
            <div :class="['now-filter', nowCondition.column.dimensionType]">
              <div class="name">{{ nowCondition.column.columnTitle + ' ' + nowCondition.column.columnName }}</div>
              <div style="color: #999">{{ datatypeMap[nowCondition.column.viewDataType] }}</div>
            </div>
          </el-form-item>
          <el-form-item label="连接方式">
            <el-radio-group v-model="nowCondition.connectType">
              <el-radio label="and">且</el-radio>
              <el-radio label="or">或</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item label="枚举来源" v-show="countEnumShow()">
            <el-radio-group v-model="nowCondition.enumSource" @change="nowCondition.enumId == ''">
              <el-radio label="1">原始数据聚合</el-radio>
              <el-radio label="2">api</el-radio>
              <el-radio label="3">自定义字典</el-radio>
            </el-radio-group>
            <el-button size="mini" plain type="primary" @click="onGetEnumData" style="margin-left: 20px"> 获取 </el-button>
          </el-form-item>
          <el-form-item label="选择api" v-if="countEnumShow() && nowCondition.enumSource === '2'">
            <el-cascader
              v-model="nowCondition.enumId"
              :options="apiList"
              size="mini"
              popper-class="bigdata-data-selector"
              :props="{ expandTrigger: 'hover', emitPath: false }"
              filterable
              :show-all-levels="false"
            ></el-cascader>
          </el-form-item>
          <el-form-item label="选择字典" v-if="countEnumShow() && nowCondition.enumSource === '3'">
            <el-select v-model="nowCondition.enumId">
              <el-option v-for="(item, i) of dictList" :key="i" :value="item.id" :label="item.keyCode"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="过滤条件">
            <div class="filter-item" v-for="(condition, i) of nowCondition.conditions" :key="i">
              <el-select size="mini" v-model="condition.function" style="width: 100px; margin-right: 10px" placeholder="选择条件" @change="onFunctionChange">
                <el-option v-for="func of functions[nowCondition.column.viewDataType]" :key="func.function" :value="func.function" :label="func.label"></el-option>
              </el-select>
              <!-- 日期类型 -->
              <template v-if="nowCondition.column.viewDataType === 'DATETIME'">
                <el-select v-model="condition.useParam" style="width: 95px; margin-right: 5px" @change="onUseParamChange(condition)">
                  <el-option label="普通参数" :value="false"></el-option>
                  <el-option label="全局参数" :value="true"></el-option>
                </el-select>
                <template v-if="condition.useParam">
                  <el-cascader
                    v-model="condition.paramKey"
                    :options="paramList"
                    :show-all-levels="false"
                    filterable
                    :props="{ expandTrigger: 'click', emitPath: false, value: 'paramKey' }"
                    clearable
                  ></el-cascader>
                </template>
                <template v-else>
                  <el-select v-model="condition.timeType" style="width: 95px; margin-right: 5px" @change="onTimeTypeChange(condition)">
                    <el-option label="绝对时间" value="absolute"></el-option>
                    <el-option label="相对时间" value="relative"></el-option>
                  </el-select>
                  <template v-if="condition.timeType === 'relative'">
                    <el-input style="width: 120px; margin-right: 5px" v-model="condition.values[0]">
                      <template slot="append"> {{ timeTypeMap[nowCondition.column.timeDataFormat] }}</template>
                    </el-input>
                    <el-select v-model="condition.countType" style="width: 60px">
                      <el-option label="前" value="left"></el-option>
                      <el-option label="后" value="right"></el-option>
                    </el-select>
                  </template>
                  <template v-else>
                    <template v-if="nowCondition.dateType === 'time'">
                      <el-date-picker style="width: 200px" v-model="condition.values[0]" type="datetime" placeholder="选择日期时间" :value-format="nowCondition.dateFormat"></el-date-picker>
                      <el-date-picker
                        v-if="condition.function === 'between'"
                        style="width: 200px"
                        v-model="condition.values[1]"
                        type="datetime"
                        placeholder="选择日期时间"
                        :value-format="nowCondition.dateFormat"
                      ></el-date-picker>
                    </template>
                    <template v-else-if="['year', 'month', 'date'].includes(nowCondition.dateType)">
                      <el-date-picker style="width: 200px" v-model="condition.values[0]" :type="nowCondition.dateType" placeholder="选择日期" :value-format="nowCondition.dateFormat"></el-date-picker>
                      <el-date-picker
                        v-if="condition.function === 'between'"
                        style="width: 200px"
                        v-model="condition.values[1]"
                        :type="nowCondition.dateType"
                        placeholder="选择日期"
                        :value-format="nowCondition.dateFormat"
                      ></el-date-picker>
                    </template>
                    <template v-else>
                      <el-time-select style="width: 200px" v-model="condition.values[0]" placeholder="选择时间" :value-format="nowCondition.dateFormat"></el-time-select>
                      <el-time-select
                        v-if="condition.function === 'between'"
                        style="width: 200px"
                        v-model="condition.values[1]"
                        placeholder="选择时间"
                        :value-format="nowCondition.dateFormat"
                      ></el-time-select>
                    </template>
                  </template>
                </template>
              </template>
              <template v-else>
                <el-select v-model="condition.useParam" style="width: 95px; margin-right: 5px" @change="onUseParamChange(condition)">
                  <el-option label="普通参数" :value="false"></el-option>
                  <el-option label="全局参数" :value="true"></el-option>
                </el-select>
                <template v-if="condition.useParam">
                  <el-cascader
                    v-model="condition.paramKey"
                    :options="paramList"
                    :show-all-levels="false"
                    filterable
                    :props="{ expandTrigger: 'click', emitPath: false, value: 'paramKey' }"
                    clearable
                  ></el-cascader>
                </template>
                <template v-else>
                  <template v-if="['in', 'notIn'].includes(condition.function)">
                    <el-cascader
                      v-model="condition.values"
                      :options="nowCondition.options"
                      size="mini"
                      :props="{ expandTrigger: 'hover', emitPath: false, multiple: true, label: 'VALUE', value: 'KEY' }"
                      filterable
                      :show-all-levels="false"
                      collapse-tags
                      clearable
                    ></el-cascader>
                    <el-button size="mini" @click="onEnumSelectAll(nowCondition)" type="primary"> 全选</el-button>
                  </template>
                  <template v-else-if="['indexIn'].includes(condition.function)">
                    <el-input style="width: 200px" size="mini" v-model="condition.values[0]" placeholder="默认使用第几条"></el-input>
                  </template>
                  <span v-else-if="['isnull', 'notnull'].includes(condition.function)"></span>
                  <el-input v-else style="width: 200px" size="mini" v-model="condition.values[0]" placeholder="输入值"></el-input>
                </template>
              </template>
              <i class="el-icon-delete" v-show="nowCondition.conditions.length > 1" @click="onConditionDel(i)"></i>
            </div>
            <el-button size="mini" type="success" plain @click="onConditionAdd" v-show="canAddCondition"> 添加条件 </el-button>
          </el-form-item>
          <div class="btns" style="display: flex; justify-content: end; margin-top: 30px">
            <el-button type="primary" size="small" @click="showCondition = false" style="width: 100px"> 确定</el-button>
            <el-button size="small" @click="showCondition = false" style="width: 100px"> 取消</el-button>
          </div>
        </el-form>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import util from '../wey'
import GlobalFilterNode from '@/views/dataset/comps/globalFilterNode'
import { dateTypeMap, fieldDateFormats, functions, timeTypeMap, columnKeys } from '@/utils/dict'
import { getEnumData, onEnumSelectAll } from '@/utils/util'
import { dataapicategoryList, dataapiList } from '@/api/newbi/report'
import { dictList } from '@/api/newbi/dict'
import { categoryList, paramList } from '@/api/newbi/globalParams'

export default {
  components: { GlobalFilterNode },
  model: { prop: 'show', event: 'change' },
  props: ['show', 'cubeId', 'fields', 'filterJson'],
  data() {
    return {
      dateTypeMap,
      fieldDateFormats,
      functions,
      timeTypeMap,
      columnKeys,
      datatypeMap: { NUMBER: '数字', STRING: '字符串', DATETIME: '时间' },
      apiList: [],
      dictList: [],
      searchKey: '',
      filter: { filterList: [], filterRelation: { where: { conditions: [], filters: [], relation: 'AND' } } },
      defaultFilter: '{"filterList":[],"filterRelation":{"where":{"conditions":[],"filters":[],"relation": "AND"}}}',
      showCondition: false,
      nowCondition: null,
      draggingNode: null,
      draggingIndex: 0,
      paramList: []
    }
  },
  provide() {
    return {
      editFilterByUniqId: this.editFilterByUniqId,
      onNodeDrag: this.onNodeDrag,
      onNodeDrop: this.onNodeDrop,
      onDelFilter: this.onDelFilter
    }
  },
  computed: {
    searchedFields() {
      return this.fields.filter((i) => i.columnTitle.includes(this.searchKey))
    },
    // 能否添加过滤条件
    canAddCondition() {
      if (!this.nowCondition) return false
      let func = this.nowCondition.conditions[0].function
      return !(func === 'in' || func === 'notIn' || func === 'indexIn')
    }
  },
  watch: {
    show(val) {
      if (!val) return
      this.filter = JSON.parse(this.filterJson || this.defaultFilter)
    }
  },
  created() {
    this.getInitData()
  },
  methods: {
    onUseParamChange(condition) {
      if (condition.useParam) {
        condition.values = ['', '']
      } else {
        condition.paramKey = ''
      }
    },
    setJson() {
      let allConditions = this.filter.filterList.reduce((r, i) => {
        return r.concat(i.conditions.map((j) => ({ ...j, title: i.column.columnTitle })))
      }, [])
      for (let i = 0; i < allConditions.length; i++) {
        if (allConditions[i].useParam && !allConditions[i].paramKey) {
          return this.$message({ type: 'warning', message: `过滤条件【${allConditions[i].title}】未设置全局参数` })
        }
      }
      this.filter.filterList.forEach((i) => (i.options = []))
      let json = this.filter.filterList.length ? JSON.stringify(this.filter) : ''
      this.$emit('set', json)
    },
    // 清除空节点
    clearNullNode(parent, item, index) {
      item.filters.forEach((node, i) => {
        this.clearNullNode(item, node, i)
      })
      if (!item.filters.length && !item.conditions.length) {
        parent.filters.splice(index, 1)
      }
    },
    // 编辑某个条件
    editFilterByUniqId({ uniqId }) {
      this.nowCondition = this.filter.filterList.find((i) => i.uniqId == uniqId)
      this.showCondition = true
      if (this.nowCondition.conditions[0].useParam) return
      let func = this.nowCondition.conditions[0].function
      if (func === 'in' || func === 'notIn' || func === 'indexIn') {
        this.onGetEnumData()
      }
    },
    // 开始拖拽某节点
    onNodeDrag(node, index) {
      this.draggingNode = node
      this.draggingIndex = index
    },
    // 节点拖拽完成时
    onNodeDrop(node) {
      let item = this.draggingNode.conditions.splice(this.draggingIndex, 1)[0]
      node.conditions.push(item)
      let rootNode = this.filter.filterRelation.where
      rootNode.filters.forEach((node, index) => {
        this.clearNullNode(rootNode, node, index)
      })
    },
    // 删除条件时
    onDelFilter(item, node, i) {
      node.conditions.splice(i, 1)
      let index = this.filter.filterList.findIndex((i) => i.uniqId == item.uniqId)
      this.filter.filterList.splice(index, 1)
      let rootNode = this.filter.filterRelation.where
      rootNode.filters.forEach((node, index) => {
        this.clearNullNode(rootNode, node, index)
      })
    },
    // 过滤器添加条件
    onConditionAdd() {
      this.nowCondition.conditions.push({
        function: 'eq',
        values: ['', ''],
        timeType: 'absolute',
        countType: 'left',
        useParam: false,
        paramKey: ''
      })
    },
    // 过滤器删除条件
    onConditionDel(i) {
      this.nowCondition.conditions.splice(i, 1)
    },
    onEnumSelectAll(filter) {
      onEnumSelectAll(filter)
    },
    // 条件时间类型变化时
    onTimeTypeChange(condition) {
      if (condition.timeType === 'relative') {
        condition.values = [1]
      } else {
        condition.values = ['']
      }
    },
    // 计算函数变化时
    async onFunctionChange(func) {
      if (['in', 'notIn', 'indexIn'].includes(func)) {
        this.nowCondition.conditions = [
          {
            function: func,
            values: [],
            timeType: 'absolute',
            countType: 'left',
            useParam: false,
            paramKey: ''
          }
        ]
      }
    },
    // 获取初始化工具数据
    getInitData() {
      // 获取api列表
      dataapicategoryList().then((res) => {
        let category = res.data.data
        dataapiList({ apiFormal: 1, apiTypes: '1,2' }).then((res) => {
          let list = res.data.data
          this.apiList = category
            .map((i) => {
              return {
                label: i.categoryName,
                value: i.id,
                children: list
                  .filter((j) => j.categoryId === i.id)
                  .map((k) => ({
                    label: k.apiName,
                    value: k.id,
                    key: k.apiKey
                  }))
              }
            })
            .filter((i) => i.children.length)
        })
      })
      dictList({ current: 1, size: 10000 }).then((res) => {
        this.dictList = res.data.data.records
      })
      categoryList({ size: 10000, current: 1 }).then((res) => {
        let list = res.data.data.records
        let parents = list.filter((i) => !i.parentId)
        let categoryList = []
        list.forEach((i) => {
          i.children = []
          if (i.parentId) {
            let parent = parents.find((j) => j.id == i.parentId)
            parent.hasChild = true
            i.label = parent.typeName + ' / ' + i.typeName
            categoryList.push(i)
          } else {
            i.label = i.typeName
          }
        })
        categoryList = categoryList.concat(parents.filter((i) => !i.hasChild))
        paramList({ size: 10000, current: 1 }).then((res) => {
          let params = res.data.data.records
          params.forEach((i) => {
            i.label = i.paramName
            let parent = categoryList.find((j) => j.id == i.typeId)
            parent.children.push(i)
          })
          this.paramList = categoryList
        })
      })
    },
    // 获取枚举值列表
    onGetEnumData() {
      if (!this.nowCondition.options.length) {
        getEnumData(this.nowCondition, this.cubeId, '', '', true)
      }
    },
    // 判断是否展示枚举选项
    countEnumShow() {
      if (this.nowCondition.conditions[0].useParam) return false
      let func = this.nowCondition.conditions[0].function
      return func === 'in' || func === 'notIn' || func === 'indexIn'
    },
    // 添加条件时
    onAddFilter(field) {
      let column = util.filterFields([field], this.columnKeys)[0]
      let nowField = { column }
      nowField.uniqId = util.getRandomStr(7)
      nowField.cubeColumnId = field.id
      nowField.connectType = 'and'
      nowField.conditions = [
        {
          function: 'eq',
          values: ['', ''],
          timeType: 'absolute',
          countType: 'left',
          useParam: false,
          paramKey: ''
        }
      ]
      nowField.asFilter = true
      nowField.options = []
      nowField.enumSource = '1'
      nowField.enumId = ''
      if (nowField.viewDataType === 'DATETIME') {
        nowField.dateType = this.dateTypeMap[field.timeDataFormat]
        nowField.dateFormat = this.fieldDateFormats.find((i) => i.value === field.timeDataFormat).label
      }
      this.filter.filterList.push(nowField)
      this.filter.filterRelation.where.conditions.push({
        uniqId: nowField.uniqId,
        columnTitle: column.columnTitle
      })
    }
  }
}
</script>
<style lang="scss">
.dataset-global-filter {
}
</style>
