<template>
  <div
    :class="{ 'my-chart': 1, active: select }"
    ref="box"
    :style="countStyle"
    v-loading="loading"
    element-loading-text="拼命加载中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(255,255,255, 0.3)"
  >
    <component
      :chartId="id"
      :index="index"
      ref="chart"
      :is="name"
      class="chart-box"
      :option="option"
      :config="config"
      :modalSet="modalSet"
      :site="site"
      :isEdit="isEdit"
      :scale="scale"
      :ext="ext"
      :charts="charts"
      @preview="preview"
    ></component>
    <el-button
      class="btn"
      size="mini"
      type="primary"
      @click="showFilter = true"
      v-if="modalSet"
    >
      筛选
    </el-button>
    <el-drawer
      :title="title + (config.dataType == 'CUBE' ? ' 筛选' : ' 参数')"
      :visible.sync="showFilter"
      v-if="modalSet"
      append-to-body
      custom-class="newbi-preview-filter"
    >
      <div class="item-list" v-if="config.dataType == 'CUBE'">
        <div
          class="item"
          v-for="(nowFilter, i) of config.filter"
          :key="i"
          v-show="nowFilter.asFilter"
        >
          <div class="name">{{ nowFilter.columnTitle }}</div>
          <div
            class="filter-item"
            v-for="(condition, i) of nowFilter.conditions"
            :key="i"
          >
            <div class="condition">
              {{
                functionMap[nowFilter.viewDataType + "-" + condition.function]
              }}
            </div>
            <div class="value">
              <!-- 日期类型 -->
              <template v-if="nowFilter.viewDataType == 'DATETIME'">
                <template v-if="condition.timeType == 'relative'">
                  <el-input
                    style="width: 120px; margin-right: 5px"
                    v-model="condition.values[0]"
                  >
                    <template slot="append">
                      {{ timeTypeMap[nowFilter.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="nowFilter.dateType == 'time'">
                    <el-date-picker
                      v-model="condition.values[0]"
                      type="datetime"
                      placeholder="选择日期时间"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-date-picker>
                    <el-date-picker
                      v-if="condition.function == 'between'"
                      v-model="condition.values[1]"
                      type="datetime"
                      placeholder="选择日期时间"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-date-picker>
                  </template>
                  <template
                    v-else-if="
                      ['year', 'month', 'date'].includes(nowFilter.dateType)
                    "
                  >
                    <el-date-picker
                      v-model="condition.values[0]"
                      :type="nowFilter.dateType"
                      placeholder="选择日期"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-date-picker>
                    <el-date-picker
                      v-if="condition.function == 'between'"
                      v-model="condition.values[1]"
                      :type="nowFilter.dateType"
                      placeholder="选择日期"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-date-picker>
                  </template>
                  <template v-else>
                    <el-time-select
                      v-model="condition.values[0]"
                      placeholder="选择时间"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-time-select>
                    <el-time-select
                      v-if="condition.function == 'between'"
                      v-model="condition.values[1]"
                      placeholder="选择时间"
                      :value-format="nowFilter.dateFormat"
                    >
                    </el-time-select>
                  </template>
                </template>
              </template>
              <template v-else>
                <div
                  class="cascader"
                  v-if="['in', 'notIn'].includes(condition.function)"
                >
                  <el-cascader
                    v-model="condition.values"
                    :options="nowFilter.options"
                    :props="{
                      expandTrigger: 'hover',
                      emitPath: false,
                      multiple: true,
                      label: 'VALUE',
                      value: 'VALUE',
                    }"
                    filterable
                    :show-all-levels="false"
                    collapse-tags
                    clearable
                  ></el-cascader>
                  <el-button
                    size="mini"
                    @click="onEnumSelectAll(nowFilter)"
                    type="primary"
                  >
                    全选
                  </el-button>
                </div>
                <el-input
                  v-else
                  size="mini"
                  v-model="condition.values[0]"
                  placeholder="输入值"
                ></el-input>
              </template>
            </div>
          </div>
        </div>
      </div>
      <div class="item-list" v-else>
        <el-form size="mini" label-width="80px" class="params-form">
          <el-form-item
            v-for="(param, i) of config.params"
            :key="i"
            :label="param.key"
          >
            <el-input
              v-if="param.datatype == 'string'"
              v-model="param.def"
            ></el-input>
            <el-input
              v-if="param.datatype == 'number'"
              type="number"
              v-model="param.def"
            ></el-input>
            <el-date-picker
              v-if="param.datatype == 'date'"
              v-model="param.def"
              type="date"
              placeholder="选择日期"
              value-format="yyyyMMdd"
            >
            </el-date-picker>
            <el-date-picker
              v-if="param.datatype == 'month'"
              v-model="param.def"
              type="month"
              placeholder="选择月"
              value-format="yyyyMM"
            >
            </el-date-picker>
            <el-time-picker
              v-if="param.datatype == 'time'"
              v-model="param.def"
              placeholder="选择时间"
              value-format="HH:mm:ss"
            >
            </el-time-picker>
            <el-date-picker
              v-if="param.datatype == 'timestamp'"
              v-model="param.def"
              type="date"
              placeholder="选择日期"
              value-format="timestamp"
            >
            </el-date-picker>
            <el-time-picker
              v-if="param.datatype == 'timestamp'"
              v-model="param.def"
              placeholder="选择时间"
              value-format="timestamp"
            >
            </el-time-picker>
          </el-form-item>
        </el-form>
      </div>
      <div class="btns">
        <el-button
          type="success"
          icon="el-icon-refresh"
          size="small"
          @click="preview(true, false, [], true)"
        >
          刷新
        </el-button>
      </div>
    </el-drawer>
  </div>
</template>
<script>
import util from "../../../util/wey";
import { chartPreview } from "../../../api/newbi/bigdata";
import { dataapiDetail, openurl } from "../../../api/report/report";
import { optionList } from "../../../api/newbi/bigdata";
import { columnKeys, functions, timeTypeMap } from "../dict";
export default {
  props: [
    "name",
    "title",
    "site",
    "option",
    "select",
    "config",
    "modalSet",
    "index",
    "id",
    "nowChart",
    "isEdit",
    "scale",
    "now",
    "ext",
    "charts",
  ],
  data() {
    let functionMap = Object.entries(functions).reduce((res, [type, arr]) => {
      arr.forEach((i) => (res[type + "-" + i.function] = i.label));
      return res;
    }, {});
    return {
      timeTypeMap,
      columnKeys,
      functionMap,
      loading: false,
      showFilter: false,
      task: null,
    };
  },
  computed: {
    countStyle() {
      let flag = this.nowChart && this.nowChart.key == this.index;
      let { w, h, x, y, z, opacity, bgColor, hiddened } = this.site;
      return {
        zIndex: z + (flag ? 10000 : 0),
        opacity: opacity / 100,
        backgroundColor: bgColor,
        width: w + "px",
        height: h + "px",
        left: x + "px",
        top: y + "px",
        visibility: hiddened ? "hidden" : "visible",
        position: "absolute",
      };
    },
  },
  created() {
    if (!this.modalSet) return;
    let list = this.config.filter;
    if (!list.length) return;
    list.forEach((item) => {
      if (!item.conditions.length) return;
      let func = item.conditions[0].function;
      if (func == "in" || func == "notIn") {
        this.getEnumData(item);
      }
    });
  },
  methods: {
    getOptionValue(arr, item) {
      if (item.children) {
        item.children.forEach((i) => {
          this.getOptionValue(arr, i);
        });
      } else {
        arr.push(item.VALUE);
      }
    },
    onEnumSelectAll(filter) {
      let options = filter.options;
      let arr = [];
      options.forEach((i) => this.getOptionValue(arr, i));
      filter.conditions[0].values = arr;
    },
    getInitGlobalFilters() {
      let initFilters = this.charts
        .filter((i) => i.name == "new-filter")
        .reduce((r, i) => r.concat(i.ext.filterList), [])
        .filter((i) => i.chartList.find((j) => j.chartKey == this.index));
      let filters = initFilters.filter((i) => i.filterType == "normal");
      filters = filters.map((i) => {
        let field = i.chartList.find((j) => j.chartKey == this.index).field;
        return { ...field, ...i };
      });
      filters = filters.concat(this.getSpecialFilters(initFilters));
      return filters;
    },
    // 根据月份计算季度
    countQuarter(month) {
      if (month < 4) return 1;
      if (month < 7) return 2;
      if (month < 10) return 3;
      return 4;
    },
    // 联通日期筛选配置
    getSpecialFilters(globalFilters) {
      let specialFilters = globalFilters.filter(
        (i) => i.filterType == "special"
      );
      specialFilters = specialFilters.reduce((r, i) => {
        let thatChart = i.chartList.find((j) => j.chartKey == this.index);
        // 存入时间维度类型字段筛选器
        if (thatChart.tid) {
          r.push({
            ...thatChart.tfield,
            connectTime: "where",
            connectType: "and",
            conditions: [{ function: "eq", values: [i.dateType] }],
          });
        }
        // 处理时间维度值筛选器
        let { time, dateType } = i;
        let value1 = time[0];
        let value2 = time[1];
        let v1, v2;
        if (dateType == "QUARTER") {
          v1 =
            value1.slice(0, 4) +
            this.countQuarter(parseInt(value1.slice(4, 6)));
          v2 =
            value2.slice(0, 4) +
            this.countQuarter(parseInt(value2.slice(4, 6)));
        } else {
          v1 = value1;
          v2 = value2;
        }
        r.push({
          ...thatChart.vfield,
          connectTime: "where",
          connectType: "and",
          conditions: [
            { function: "between", values: [parseInt(v1), parseInt(v2)] },
          ],
        });
        return r;
      }, []);
      return specialFilters;
    },
    countCondition(condition, filter) {
      let { values, timeType, countType } = condition;
      if (
        filter.viewDataType != "DATETIME" ||
        timeType != "relative" ||
        !values[0]
      ) {
        return {
          function: condition.function,
          values: values.filter((j) => j),
        };
      }
      let { dateType, dateFormat } = filter;
      let now = new Date();
      if (dateType == "year") {
        if (countType == "left") {
          now.setFullYear(now.getFullYear() - values[0]);
        } else {
          now.setFullYear(now.getFullYear() + values[0]);
        }
      } else if (dateType == "month") {
        if (countType == "left") {
          now.setMonth(now.getMonth() - values[0]);
        } else {
          now.setMonth(now.getMonth() + values[0]);
        }
      } else if (dateType == "date") {
        if (countType == "left") {
          now.setDate(now.getDate() - values[0]);
        } else {
          now.setDate(now.getDate() + values[0]);
        }
      } else if (dateType == "hour") {
        if (countType == "left") {
          now.setHours(now.getHours() - values[0]);
        } else {
          now.setHours(now.getHours() + values[0]);
        }
      } else if (dateType == "minute") {
        if (countType == "left") {
          now.setMinutes(now.getMinutes() - values[0]);
        } else {
          now.setMinutes(now.getMinutes() + values[0]);
        }
      } else {
        if (countType == "left") {
          now.setSeconds(now.getSeconds() - values[0]);
        } else {
          now.setSeconds(now.getSeconds() + values[0]);
        }
      }
      let fmt = dateFormat.replaceAll("d", "D");
      let val = moment(now).format(fmt);
      return {
        function: condition.function,
        values: [val],
      };
    },
    // 获取枚举可选值
    getEnumData(filter) {
      let { enumSource, enumId } = filter;
      if (enumSource == "1") {
        filter.loading = true;
        let { tableName, columnName } = filter;
        optionList({
          tableName,
          columnName,
          cubeDataId: this.config.dataId,
        }).then((res) => {
          filter.options = res.data.data.map((i) => ({
            VALUE: i[columnName],
          }));
          filter.loading = false;
        });
      } else {
        if (!enumId) {
          return this.$message({ message: "请选择api", type: "warning" });
        }
        filter.loading = true;
        dataapiDetail(enumId).then((res) => {
          let { apiKey } = res.data.data;
          openurl(apiKey).then((res) => {
            filter.loading = false;
            let data = res.data.data;
            if (!data.length) {
              filter.options = data;
            }
            if (data[0].ID) {
              let tree = XEUtils.toArrayTree(data, {
                strict: false,
                key: "ID",
                parentKey: "PID",
                sortKey: "CORDER",
              });
              tree.forEach(this.clearChildren);
              filter.options = tree;
            } else {
              filter.options = data;
            }
          });
        });
      }
    },
    // 去掉为空的children
    clearChildren(node) {
      if (!node.children) return;
      if (!node.children.length) {
        delete node.children;
      } else {
        node.children.forEach(this.clearChildren);
      }
    },
    initPreview() {
      if (this.id && this.modalSet) {
        this.preview(true, true, [], true);
        if (this.option.intervalSwitch) {
          setTimeout(() => {
            this.task = setInterval(() => {
              // 如果当前页展示，发起定时请求
              if (this.now) {
                this.preview(false, true, [], true);
              }
            }, parseInt(this.option.intervalTime));
          }, parseInt(this.option.intervalTime));
        }
      }
    },
    preview(loading, self, receiveFilters = [], init) {
      if (this.site.hiddened) return;
      let { config, modalSet } = this;
      if (!modalSet) return;
      if (parseInt(config.dataId) < 1) {
        if (!self) {
          this.$message({ message: "请选择数据来源", type: "warning" });
        }
        return;
      }
      for (let i = 0; i < modalSet.length; i++) {
        if (modalSet[i].require && !config[modalSet[i].key].length) {
          if (!self) {
            this.$message({
              message: "请选择" + modalSet[i].name + "字段",
              type: "warning",
            });
          }
          return;
        }
      }
      if (config.dataType == "CUBE") {
        this.previewCube(loading, receiveFilters, init);
      } else if (config.dataType == "API") {
        this.previewApi(loading);
      }
    },
    previewApi(loading) {
      dataapiDetail(this.config.dataId).then((res) => {
        let { apiKey } = res.data.data;
        this.loading = loading;
        let paramObject = this.config.params.reduce((r, i) => {
          if (i.key) {
            return { ...r, [i.key]: i.def };
          } else {
            return r;
          }
        }, {});
        openurl(apiKey, paramObject)
          .then((apiRes) => {
            this.$refs.chart.update(apiRes.data.data);
          })
          .finally(() => (this.loading = false));
      });
    },
    previewCube(loading, receiveFilters, init) {
      let { config, modalSet } = this;
      let sortList = config.sort.map((sort) => {
        return {
          column: util.filterFields([sort], this.columnKeys)[0],
          orderType: sort.orderType,
        };
      });
      let columnList;
      let filterList = config.filter;
      // 钻取配置
      if (config.zuanFlag) {
        let key = modalSet.find((i) => i.zuan).key;
        let zuanField = { ...config.zuan[config.zuanLevel], type: key };
        columnList = modalSet
          .reduce((r, s) => {
            return r.concat(config[s.key].map((i) => ({ ...i, type: s.key })));
          }, [])
          .filter((i) => !i.zuan);
        columnList.push(zuanField);
        let availableFilters = this.config.zuan.slice(0, this.config.zuanLevel);
        availableFilters = JSON.parse(JSON.stringify(availableFilters));
        let appendFilters = availableFilters.map((item, index) => {
          return {
            ...item,
            connectTime: "where",
            connectType: "and",
            conditions: [
              {
                function: "eq",
                values: [this.config.zuanStack[index]],
              },
            ],
          };
        });
        filterList = filterList.concat(appendFilters);
      } else {
        columnList = modalSet.reduce((r, s) => {
          return r.concat(config[s.key].map((i) => ({ ...i, type: s.key })));
        }, []);
      }
      // ----
      // 全局筛选配置|普通
      let globalFilters = receiveFilters.filter((i) =>
        i.chartList.find((j) => j.chartKey == this.index)
      );
      let filters = globalFilters.filter((i) => i.filterType == "normal");
      filters = filters.map((i) => {
        let field = i.chartList.find((j) => j.chartKey == this.index).field;
        return { ...field, ...i };
      });
      filterList = filterList.concat(filters);
      // ----
      // 全局筛选配置|联通时间
      let specialFilters = this.getSpecialFilters(globalFilters);
      filterList = filterList.concat(specialFilters);
      // init初次加载读取全局筛选
      if (init) {
        let initGlobalFilters = this.getInitGlobalFilters();
        filterList = filterList.concat(initGlobalFilters);
      }
      // --
      columnList = util.filterFields(columnList, this.columnKeys);
      filterList = filterList.map((filter) => {
        return {
          column: util.filterFields([filter], this.columnKeys)[0],
          connectTime: filter.connectTime,
          connectType: filter.connectType,
          conditions: filter.conditions.map((i) =>
            this.countCondition(i, filter)
          ),
          dateType: filter.dateType,
          dateFormat: filter.dateFormat,
        };
      });
      let nowConfig = {
        component: {
          limitVal: config.limit,
          useType: config.dataType,
          cubeDataId: config.dataId,
        },
      };
      nowConfig.columnList = JSON.stringify(columnList);
      nowConfig.filterList = JSON.stringify(filterList);
      nowConfig.sortList = JSON.stringify(sortList);
      this.loading = loading;
      // logjson(columnList);
      // logjson(filterList);
      chartPreview(nowConfig)
        .then((res) => {
          //找出自定义公式数组列表
          let columnList = JSON.parse(nowConfig.columnList).filter(
            (item) => item.numberDataFormat === "CUSTOM"
          );
          let { dataList, fieldDict } = res.data.data;
          let data = util.arrReplaceKeys(dataList, fieldDict, columnList);
          this.$refs.chart.update(data);
        })
        .finally(() => (this.loading = false));
    },
  },
};
</script>
<style lang="scss">
.my-chart {
  position: absolute;
  .chart-box {
    width: 100%;
    height: 100%;
  }
  &.active {
    //border: 1px dashed #ccc;
    touch-action: none;
  }
  .btn {
    position: absolute;
    right: 0;
    top: 0;
    transition: 0.2s;
    opacity: 0;
    &:hover {
      opacity: 1;
    }
  }
}
.newbi-preview-filter {
  width: 500px !important;
  .item {
    margin: 10px;
    padding: 10px;
    border-bottom: 1px solid #ccc;
    &:last-of-type {
      border-bottom: none;
    }
    .name {
      font-size: 16px;
      font-weight: 600;
      color: #666;
      padding-bottom: 5px;
    }
    .filter-item {
      display: flex;
      padding-left: 20px;
      align-items: center;
      padding-bottom: 5px;
      .condition {
        flex: 0 0 60px;
        text-align: right;
        font-size: 14px;
        margin-right: 5px;
        color: #666;
      }
      .value {
        flex: 1;
        & > * {
          width: 100%;
        }
        .cascader {
          display: flex;
          .el-cascader {
            flex: 1;
          }
        }
      }
    }
  }
  .el-drawer__body {
    display: flex;
    flex-direction: column;
    .item-list {
      overflow-y: auto;
      flex: 1;
    }
    .btns {
      border-top: 1px solid #999;
      flex: 0 0 200px;
      .el-button {
        display: block;
        margin: 80px auto 0;
      }
    }
  }
}
</style>
