import * as echarts from "echarts";

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

/** 地图类 */
export class Map {
  /** 地图标签 */
  static geoLabel = {
    /** 是否显示 */
    show: true,
    /** 文本颜色 */
    color: "black",
    /** 字体粗细 */
    fontWeight: "normal",
    /** 字号 */
    fontFamily: "sans-serif",
    /** 字体大小 */
    fontSize: 12,
    /** 背景色 */
    backgroundColor: "transparent",
    /** 边框色 */
    borderColor: "",
    /** 边框类型 */
    borderType: "solid",
    /** 圆角边框 */
    borderRadius: 0,
    /** 文字描边颜色 */
    textBorderColor: "",
    /** 文字边框宽度 */
    textBorderWidth: 0,
    /** 文字阴影颜色 */
    textShadowColor: "",
    /** 文字阴影长度 */
    textShadowBlur: 0,
    /** 富文本 */
    rich: {},
  };
  /** 地图提示框 */
  static getTooltip = {};
  /** 地图项目样式 */
  static geoItemStyle = {
    /** 区域样式 */
    areaColor: {
      type: "radial",
      x: 1,
      y: 1,
      r: 3,
      /** 区域颜色 */
      colorStops: this.getMapGradColor(),
      globalCoord: false,
    },
    /** 边框大小 */
    borderWidth: 1,
    /** 边框颜色 */
    borderColor: "rgba(104, 152, 190, 1)",
    /** 阴影颜色 */
    shadowColor: "rgba(104, 152, 190, 1)",
    /** 阴影水平方向偏移量 */
    shadowOffsetX: -2,
    /** 阴影垂直方向偏移量 */
    shadowOffsetY: 2,
    /** =文字块的背景阴影长度 */
    shadowBlur: 10,
  };
  /** 地图选中状态下样式 */
  static geoEmphasis = {
    label: {
      color: "#ffffff",
    },
    itemStyle: {
      /** 选中区域颜色 */
      areaColor: "#a5d4fe",
    },
  };
  /** 地图地区 */
  static geoRegions = {};
  /** 图表背景色 */
  static mapBackgroundColor = "rgb(246, 246, 246)";
  /** 地图标题 */
  static mapTitle = "";
  /** 地图区域背景渐变色 */
  static colorStops = ["rgba(223, 231, 242, 1)", "rgba(2, 99, 206, 1)"];
  /** 点位 */
  static geoPoint = {
    type: "effectScatter",
    coordinateSystem: "geo",
    geoIndex: 0,
    /** 自定义点位样式 */
    symbol: "",
    /** 点位大小 */
    symbolSize: 8,
    rippleEffect: {
      /** 点位动效缩放 */
      scale: 3.5,
    },
    itemStyle: {
      color: "#F56C6C",
    },
    encode: {
      tooltip: 2,
    },
    emphasis: {
      scale: true,
    },
    data: [],
  };
  /** 飞线 */
  static geoFlyLine = [
    {
      type: "lines",
      zlevel: 10,
      /** 飞点样式 */
      effect: {
        show: true,
        period: 6,
        /** 尾巴长度 */
        trailLength: 0.7,
        color: "orange",
        symbol: "",
        symbolSize: 5,
      },
      /** 飞线样式 */
      lineStyle: {
        show: true,
        color: "#F56C6C",
        width: 2,
        opacity: 0.4,
        /** 飞线弧度 */
        curveness: 0.2,
      },
      data: [],
    },
  ];
  /** 默认飞线 */
  static flyLine = [];
  /** 自定义飞线 */
  static cusFlyLine = [];
  /** 默认点位 */
  static point = [];
  /** 自定义点位 */
  static cusPoint = [];

  /**
   * 图表渐变色
   * @returns 图表渐变色
   */
  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 f = this.geoFlyLine;
    f[0].data = this.addFlyLine(mapData);
    f[0].effect.symbol =
      f[0].effect.symbol == "" ? "" : "image://" + f[0].effect.symbol;

    return f;
  }

  /**
   * 获取地图配置项
   * @param mapName 地图名称
   * @returns 地图配置项
   */
  static getGeoData(mapName: string) {
    let geo = {
      /** 地图名称 */
      name: "map",
      /** 地图类型 */
      type: "map",
      /** 加载注册的地图 */
      map: mapName,
      /** 是否单独选中 */
      selectedMode: false,
      /** 鼠标缩放移动 */
      roam: true,
      /** 图形上的文本标签 */
      label: this.geoLabel,
      /** 悬浮框 */
      tooltip: this.getTooltip,
      /** 地图样式 */
      itemStyle: this.geoItemStyle,
      /** 选中状态下样式 */
      emphasis: this.geoEmphasis,
      regions: this.geoRegions,
    };
    return geo;
  }

  /**
   * 获取地图点位配置项
   * @param mapData 当前区域地图数据
   * @returns 点位配置项
   */
  static getPointData(mapData: any) {
    let p = JSON.parse(JSON.stringify(this.geoPoint));
    p.symbol = p.symbol == "" ? "" : "image://" + p.symbol;
    p.data = this.addPoint(mapData);

    return p;
  }

  /**
   * 释放资源
   * @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 mapJsonData = this.getMapJsonData(mapName); // 地图数据
    let flyLineSeries: any[] = this.getFlyLineData(mapJsonData); // 飞线数据
    let pointSeries: any = this.getPointData(mapJsonData); // 点位数据
    let geo = this.getGeoData(mapName); // geo配置项
    flyLineSeries.push(pointSeries);
    echarts.registerMap(mapName, mapJsonData); // 注册地图

    // 地图配置项
    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); // 初始化实例

      // 监听窗口变化
      window.addEventListener("resize", () => {
        _mapEcharts.resize();
      });
    }
    _mapEcharts.showLoading(); // 显示加载
    _mapEcharts.clear();
    _mapEcharts.setOption(option, { notMerge: true });
    _mapEcharts.hideLoading(); // 隐藏Loading

    // 单击左键下钻
    _mapEcharts.on("click", (params: any) => {
      if (!mapList.includes(params.name)) {
        mapList.push(params.name);
      }
      this.initMap(mapList, params.name, eleId, _mapEcharts);
    });

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

    return _mapEcharts;
  }
}
