import * as echarts from "echarts";
import { flyLineType, pointType } from "../../enum";

/** 默认飞线拼接数据 */
export interface resFlyData {
  /** 起点 */
  fromName: string;
  /** 终点 */
  toName: string;
  /** 坐标拼接 */
  coords: [number[], number[]];
}
/** 默认点位拼接数据 */
export interface resPoint {
  /** 点位名称 */
  name: string;
  /** 值（[纬度，精度,数值]） */
  value: number[];
}

/** 地图类 */
export class Map {
  /** 图表背景色 */
  static mapBackgroundColor = "rgb(246, 246, 246)";
  /** 地图区域背景渐变色 */
  static colorStops = ["rgba(223, 231, 242, 1)", "rgba(2, 99, 206, 1)"];
  /** 边框大小 */
  static borderWidth = 1;
  /** 边框颜色 */
  static borderColor = "rgba(104, 152, 190, 1)";
  /** 阴影颜色 */
  static shadowColor = "rgba(128, 217, 248, 1)";
  /** 阴影水平方向上的偏移距离 */
  static shadowOffsetX = -2;
  /** 阴影垂直方向上的偏移距离 */
  static shadowOffsetY = 2;
  /** 是否显示标签 */
  static showLabel = true;
  /** 文字块的背景阴影长度 */
  static shadowBlur = 10;
  /** 选中区域颜色 */
  static selectAreaColor = "#a5d4fe";
  /** 文字颜色 */
  static fontColor = "black";
  /** 文字粗细 */
  static fontWeight: string | number = "normal";
  /** 文字的字体系列 */
  static fontFamily: string = "sans-serif";
  /** 文字大小 */
  static fontSize = 12;
  /** 文字块背景色 */
  static fontBackgroundColor: any = "transparent";
  /** 文字块边框宽度 */
  static fontBorderColor: echarts.Color;
  /** 文字块边框描边类型 */
  static fontBorderType: string | number | number[] = "solid";
  /** 文字块的圆角 */
  static fontBorderRadius: number | number[];
  /** 文字本身的描边颜色 */
  static fontTextBorderColor: echarts.Color;
  /** 文字本身的描边宽度 */
  static fontTextBorderWidth: number;
  /** 文字本身的阴影颜色 */
  static fontTextShadowColor: echarts.Color = "transparent";
  /** 文字本身的阴影长度 */
  static fontTextShadowBlur: number;
  /** 自定义富文本样式 */
  static rich: any;
  /** 地图悬浮框 */
  static mapToolTip = {};
  /** 鼠标悬浮时文字颜色 */
  static emphasisLabelColor = "#ffffff";
  /** 飞线类型 */
  static flyLineType = flyLineType.default;
  /** 点位类型 */
  static pointType = pointType.default;
  /** 默认飞线 */
  static flyLine = [];
  /** 自定义飞线 */
  static cusFlyLine = [];
  /** 默认点位 */
  static point = [];
  /** 自定义点位 */
  static cusPoint = [];
  /** 飞点颜色 */
  static flyPointColor = "orange";
  /** 自定义飞点样式 */
  static flyPointSymbol = "";
  /** 飞点大小 */
  static flyPointSymbolSize = 5;
  /** 飞线颜色 */
  static flyLineColor = "#F56C6C";
  /** 飞线宽度 */
  static flyLineWidth = 2;
  /** 飞线弧度 */
  static flyLineCurveness = 0.2;
  /** 自定义点位样式 */
  static pointSymbol = "";
  /** 点位大小 */
  static pointSize = 8;
  /** 点位动效缩放 */
  static pointScale = 3.5;
  /** 点位颜色 */
  static pointColor = "#F56C6C";
  /** 地图标题 */
  static mapTitle = "";

  /** 组合渐变色 */
  static getMapGradColor() {
    let colorArr: any[] = [];
    /** 渐变数组长度 */
    let l = this.colorStops.length;
    let j = l - 1;
    for (let i = 0; i <= j; i++) {
      colorArr.push({
        offset: (1 / j) * i,
        color: this.colorStops[i],
      });
    }
    return colorArr;
  }
  /**
   * 获取地图边缘数据
   * @param mapName 地图名称
   * @returns 地图边缘数据Json
   */
  static getMapJsonData(mapName: string) {
    return require(`../json/${mapName}.json`);
  }

  /**
   * 添加飞线
   * @param mapData 当前区域地图数据
   * @returns 飞线数据
   */
  static addFlyLine(mapData?: any) {
    let flyData = [...this.flyLine]; // 默认飞线数据
    let cusFlyData = [...this.cusFlyLine]; // 自定义飞线数据
    let resData: resFlyData[] = [];
    let from: number[] = [];
    let to: number[] = [];
    // 默认飞线
    if (flyData != []) {
      flyData.forEach((e: any) => {
        // 初始化
        let data: resFlyData = {
          fromName: "",
          toName: "",
          coords: [[], []],
        };
        if (e[0] != "" && e[1] != "") {
          mapData.features.forEach((v: any) => {
            if (v.properties.name == e[0]) {
              from = v.properties.center;
              data.fromName = v.properties.name;
            }
            if (v.properties.name == e[1]) {
              to = v.properties.center;
              data.toName = v.properties.name;
            }
          });
          if (from != [] && to != []) {
            data.coords = [from, to];
            resData.push(data);
          }
        } else {
          resData.push({ fromName: "", toName: "", coords: [[], []] });
        }
      });
    }
    // 自定义飞线
    if (cusFlyData != []) {
      cusFlyData.forEach((e: any) => {
        resData.push(e);
      });
    }
    return resData;
  }
  /**
   * 添加点位
   * @param mapData 当前区域地图数据
   * @returns 点位数据
   */
  static addPoint(mapData?: any) {
    let resData: resPoint[] = [];
    let point = [...this.point];
    let cusPoint = [...this.cusPoint];

    // 默认点位
    if (point != []) {
      point.forEach((e) => {
        // 初始化
        let data: resPoint = {
          name: "",
          value: [],
        };
        if (e[0] != "") {
          mapData.features.forEach((v: any) => {
            if (v.properties.name == e[0]) {
              data.name = v.properties.name;
              data.value = [...v.properties.center];
            }
          });
          data.value.push(e[1]);
          resData.push(data);
        } else {
          resData.push({ name: "", value: [] });
        }
      });
    }
    // 自定义点位
    if (cusPoint != []) {
      cusPoint.forEach((e) => {
        resData.push(e);
      });
    }
    return resData;
  }

  /**
   * 获取飞线配置项数据
   * @param mapData 当前区域数据
   * @returns 飞线配置项
   */
  static getFlyLineData(mapData: any) {
    let _data = this.addFlyLine(mapData);
    let _symbol =
      this.flyPointSymbol == "" ? "" : "image://" + this.flyPointSymbol;

    let flyLineSeries = [
      {
        type: "lines",
        zlevel: 10,
        // 飞点样式
        effect: {
          show: true,
          period: 6,
          trailLength: 0.7, //尾巴长度
          color: this.flyPointColor,
          symbol: _symbol, // 自定义图片
          symbolSize: this.flyPointSymbolSize, //飞点大小
        },
        // 飞线样式
        lineStyle: {
          show: true,
          color: this.flyLineColor, // 飞线颜色
          width: this.flyLineWidth, // 飞线宽度
          opacity: 0.4,
          curveness: this.flyLineCurveness, // 弧度
        },
        data: _data,
      },
    ];
    return flyLineSeries;
  }

  /**
   * 获取地图配置项
   * @param mapName 地图名称
   * @returns 地图配置项
   */
  static getGeoData(mapName: string) {
    let geo = {
      name: "map", // 地图名称
      type: "map", // 地图类型
      map: mapName, // 加载注册的地图
      selectedMode: false, // 是否单独选中
      roam: true, // 开始鼠标事件，scale缩放、move移动
      /** 图形上的文本标签 */
      label: {
        show: this.showLabel,
        color: this.fontColor,
        fontWeight: this.fontWeight,
        fontFamily: this.fontFamily,
        fontSize: this.fontSize,
        backgroundColor: this.fontBackgroundColor,
        borderColor: this.fontBorderColor,
        borderType: this.fontBorderType,
        borderRadius: this.fontBorderRadius,
        textBorderColor: this.fontTextBorderColor,
        textBorderWidth: this.fontTextBorderWidth,
        textShadowColor: this.fontTextShadowColor,
        textShadowBlur: this.fontTextShadowBlur,
        rich: this.rich,
      },
      /** 悬浮框 */
      tooltip: this.mapToolTip,
      /** 地图样式 */
      itemStyle: {
        /** 区域样式 */
        areaColor: {
          type: "radial",
          x: 1,
          y: 1,
          r: 3,
          colorStops: this.getMapGradColor(), // 区域颜色
          globalCoord: false, // 缺省为 false
        },
        borderWidth: this.borderWidth, // 边框大小
        borderColor: this.borderColor, // 边框颜色
        shadowColor: this.shadowColor, // 阴影颜色
        shadowOffsetX: this.shadowOffsetX, // 阴影水平方向上的偏移距离
        shadowOffsetY: this.shadowOffsetY, // 阴影垂直方向上的偏移距离
        shadowBlur: this.shadowBlur, // 文字块的背景阴影长度
      },
      // 选中状态下样式
      emphasis: {
        label: {
          color: this.emphasisLabelColor,
        },
        itemStyle: {
          areaColor: this.selectAreaColor,
        },
      },
    };
    return geo;
  }

  /**
   * 获取地图点位配置项
   * @param mapData 当前区域地图数据
   * @returns 点位配置项
   */
  static getPointData(mapData: any) {
    let _symbol = this.pointSymbol == "" ? "" : "image://" + this.pointSymbol;
    let _data = this.addPoint(mapData);
    let pointSeries = {
      type: "effectScatter",
      coordinateSystem: "geo",
      geoIndex: 0,
      symbol: _symbol,
      symbolSize: this.pointSize,
      rippleEffect: {
        scale: this.pointScale,
      },
      itemStyle: {
        color: this.pointColor,
      },
      encode: {
        tooltip: 2,
      },
      emphasis: {
        scale: true,
      },
      data: _data,
    };
    return pointSeries;
  }

  /**
   * 释放资源
   * @param eleId dom元素id
   */
  static disposeMap(eleId: string) {
    let element = document.getElementById(eleId) as HTMLElement;

    let instance = echarts.getInstanceByDom(element);

    if (instance) {
      instance.dispose();
    }
  }

  /**
   * 生成地图
   * @param mapList 层级列表
   * @param mapName 选中区域名称
   * @param eleId DOM节点id
   * @param mapEcharts 地图实例
   */
  static initMap(mapList: any, mapName: any, eleId: string, mapEcharts?: any) {
    let _mapEcharts = mapEcharts;

    let timeFn: any;

    /** 地图数据 */
    let mapJsonData = this.getMapJsonData(mapName);

    /** 飞线数据 */
    let flyLineSeries: object[] = this.getFlyLineData(mapJsonData);

    /** 点位数据 */
    let pointSeries: object = this.getPointData(mapJsonData);

    flyLineSeries.push(pointSeries);

    /** 注册地图 */
    echarts.registerMap(mapName, mapJsonData);

    /** 地图数据 */
    let geo = this.getGeoData(mapName);

    /**地图配置项 */
    let option = {
      backgroundColor: this.mapBackgroundColor,
      title: {
        text: this.mapTitle,
      },
      tooltip: {
        trigger: "item",
      },
      toolbox: {
        show: true,
        orient: "vertical",
        left: "left",
        top: "center",
        feature: {
          restore: {},
          saveAsImage: {},
        },
      },
      geo: geo,
      series: flyLineSeries,
    };

    if (_mapEcharts) {
      _mapEcharts.dispose(); //销毁
    }

    let element = document.getElementById(eleId) as HTMLElement;

    _mapEcharts = echarts.getInstanceByDom(element);

    if (_mapEcharts == undefined) {
      /** 初始化实例 */
      _mapEcharts = echarts.init(element);
    }
    _mapEcharts.showLoading(); // 显示加载
    _mapEcharts.clear();
    _mapEcharts.setOption(option, { notMerge: true });
    _mapEcharts.hideLoading(); // 隐藏Loading

    // 单击左键进行地图下钻
    _mapEcharts.on("click", (params: any) => {
      // 触发双击事件后，清除单击事件，只响应双击事件
      clearTimeout(timeFn);
      timeFn = setTimeout(() => {
        if (!mapList.includes(params.name)) {
          mapList.push(params.name);
        }
        this.initMap(mapList, params.name, eleId, _mapEcharts);
      }, 200);
    });

    let canvas = document.getElementById(eleId) as HTMLElement;
    // 清除浏览器默认右键事件
    canvas.oncontextmenu = function () {
      return false;
    };
    // 单击右键，返回上一级
    _mapEcharts.on("contextmenu", () => {
      /** 数组长度 */
      let len = mapList.length;
      // 触发双击事件后，清除单击事件，只响应双击事件
      clearTimeout(timeFn);
      if (len > 1) {
        this.initMap(mapList, mapList[len - 2], eleId, _mapEcharts);
        mapList.pop();
      }
    });
  }
}
