<template>
  <component
    :chartId="id"
    :index="index"
    ref="chart"
    :is="name"
    :contentH="true"
    class="chart-box"
    :option="option"
    :config="config"
    :modalSet="modalSet"
    :site="site"
    :isEdit="isEdit"
    :charts="charts"
    :ext="ext"
    @preview="preview"
  ></component>
</template>
<script>
import util from "../../../util/wey";
import { chartPreview } from "../../../api/newbi/bigdata";
import { dataapiDetail, openurl } from "../../../api/report/report";
import { columnKeys } from "../dict";
import moment from "moment";
export default {
  props: [
    "name",
    "title",
    "site",
    "option",
    "select",
    "config",
    "modalSet",
    "index",
    "id",
    "nowChart",
    "isEdit",
    "scale",
    "charts",
    "ext",
  ],
  data() {
    return {
      columnKeys,
      loading: false,
      task: null,
    };
  },
  computed: {
    countStyle() {
      let flag = this.nowChart && this.nowChart.key == this.index;
      return {
        zIndex: this.site.z + (flag ? 10000 : 0),
        opacity: this.site.opacity / 100,
        backgroundColor: this.site.bgColor,
        visibility: this.site.hiddened ? "hidden" : "visible",
      };
    },
  },
  watch: {
    "option.intervalSwitch"() {
      clearInterval(this.task);
      if (this.option.intervalSwitch) {
        this.task = setInterval(() => {
          this.preview(false, true, [], true);
        }, parseInt(this.option.intervalTime));
      }
    },
    "option.intervalTime"() {
      clearInterval(this.task);
      if (this.option.intervalSwitch) {
        this.task = setInterval(() => {
          this.preview(false, true, [], true);
        }, parseInt(this.option.intervalTime));
      }
    },
    "config.dataId"() {
      clearInterval(this.task);
    },
  },
  methods: {
    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;
    },
    initPreview() {
      if (this.id && this.modalSet) {
        this.preview(true, true, [], true);
        if (this.option.intervalSwitch) {
          setTimeout(() => {
            this.task = setInterval(() => {
              this.preview(false, true, [], true);
            }, parseInt(this.option.intervalTime));
          }, parseInt(this.option.intervalTime));
        }
      } else {
        if (this.$refs.chart.initRender) {
          this.$refs.chart.initRender();
        }
      }
    },
    getRefLineParams(params) {
      this.$emit("getRefLineParams", params);
    },
    beforeSave() {
      if (this.$refs.chart.beforeSave) {
        // console.log(this.title + " 组件执行保存前钩子");
        return this.$refs.chart.beforeSave();
      } else {
        // console.warn(this.title + " 组件没有保存前钩子");
        return undefined;
      }
    },
    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" });
        } else {
          if (this.$refs.chart.initRender) {
            this.$refs.chart.initRender();
          }
        }
        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);
      // return;
      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));
    },
    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],
      };
    },
    onResizStop(x, y, w, h) {
      this.site.x = x;
      this.site.y = y;
      this.site.w = w;
      this.site.h = h;
    },
    onDragStop(x, y) {
      this.site.x = x;
      this.site.y = y;
    },
    onSelect(state) {
      let points = this.$refs.box.$el.getElementsByClassName("handle");
      [...points].forEach((i) => (i.style.display = state));
    },
    isjiegou() {
      this.$refs.chart.isjiegou();
    },
    jiegou() {
      this.$refs.chart.jiegou(true);
    },
    exportExcel() {
      this.$refs.chart.exportExcel();
    },
  },
};
</script>
<style lang="scss">
.my-chart {
  .chart-box {
    width: 100%;
    height: 100%;
  }
  &.active {
    border: 1px solid #4af;
    touch-action: none;
  }
}
.handle,
.vdr {
  position: absolute;
  box-sizing: border-box;
}
.handle {
  width: 6px;
  height: 6px;
  background: #4af;
  border: 1px solid #4af;
  border-radius: 50%;
  z-index: 999;
}
.handle-tl {
  top: -6px;
  left: -6px;
  cursor: nw-resize;
}
.handle-tm {
  top: -6px;
  left: 50%;
  margin-left: -5px;
  cursor: n-resize;
}
.handle-tr {
  top: -6px;
  right: -6px;
  cursor: ne-resize;
}
.handle-ml {
  left: -6px;
  cursor: w-resize;
}
.handle-ml,
.handle-mr {
  top: 50%;
  margin-top: -5px;
}
.handle-mr {
  right: -6px;
  cursor: e-resize;
}
.handle-bl {
  bottom: -6px;
  left: -6px;
  cursor: sw-resize;
}
.handle-bm {
  bottom: -6px;
  left: 50%;
  margin-left: -5px;
  cursor: s-resize;
}
.handle-br {
  bottom: -6px;
  right: -6px;
  cursor: se-resize;
}
@media only screen and (max-width: 768px) {
  [class*="handle-"]:before {
    content: "";
    left: -6px;
    right: -6px;
    bottom: -6px;
    top: -6px;
    position: absolute;
    border-radius: 50%;
  }
}
</style>
