// import * as Cesium from "@ZYWLCESIUM";
import GISTool from "@/components/ZYWLTools/GISTool.js";
// import * as _ from "lodash";
import { v4 as uuidv4 } from "uuid";

class MeasureTool {
  constructor(viewer, options = {}) {
    if (viewer && viewer instanceof Cesium.Viewer) {
      this._drawLayer = new Cesium.CustomDataSource("measureLayer");

      viewer && viewer.dataSources.add(this._drawLayer);

      this._basePath = options.basePath || "";

      this._viewer = viewer;
      this.handlers_ = new Cesium.ScreenSpaceEventHandler(
        this._viewer.scene.canvas,
      );

      this.AreaMap = new Map();
    }
  }

  /***
   * 坐标转换 84转笛卡尔
   *
   * @param {Object} {lng,lat,alt} 地理坐标
   *
   * @return {Object} Cartesian3 三维位置坐标
   */
  transformWGS84ToCartesian(position, alt) {
    if (this._viewer) {
      return position
        ? Cesium.Cartesian3.fromDegrees(
            position.lng || position.lon,
            position.lat,
            (position.alt = alt || position.alt),
            Cesium.Ellipsoid.WGS84,
          )
        : Cesium.Cartesian3.ZERO;
    }
  }

  /***
   * 坐标数组转换 笛卡尔转84
   *
   * @param {Array} WSG84Arr {lng,lat,alt} 地理坐标数组
   * @param {Number} alt 拔高
   * @return {Array} Cartesian3 三维位置坐标数组
   */
  transformWGS84ArrayToCartesianArray(WSG84Arr, alt) {
    if (this._viewer && WSG84Arr) {
      var $this = this;
      return WSG84Arr
        ? WSG84Arr.map(function (item) {
            return $this.transformWGS84ToCartesian(item, alt);
          })
        : [];
    }
  }

  /***
   * 坐标转换 笛卡尔转84
   *
   * @param {Object} Cartesian3 三维位置坐标
   *
   * @return {Object} {lng,lat,alt} 地理坐标
   */
  transformCartesianToWGS84(cartesian) {
    if (this._viewer && cartesian) {
      var ellipsoid = Cesium.Ellipsoid.WGS84;
      var cartographic = ellipsoid.cartesianToCartographic(cartesian);
      return {
        lng: Cesium.Math.toDegrees(cartographic.longitude),
        lat: Cesium.Math.toDegrees(cartographic.latitude),
        alt: cartographic.height,
      };
    }
  }

  /***
   * 坐标数组转换 笛卡尔转86
   *
   * @param {Array} cartesianArr 三维位置坐标数组
   *
   * @return {Array} {lng,lat,alt} 地理坐标数组
   */
  transformCartesianArrayToWGS84Array(cartesianArr) {
    if (this._viewer) {
      var $this = this;
      return cartesianArr
        ? cartesianArr.map(function (item) {
            return $this.transformCartesianToWGS84(item);
          })
        : [];
    }
  }

  /**
   * 84坐标转弧度坐标
   * @param {Object} position wgs84
   * @return {Object} Cartographic 弧度坐标
   *
   */
  transformWGS84ToCartographic(position) {
    return position
      ? Cesium.Cartographic.fromDegrees(
          position.lng || position.lon,
          position.lat,
          position.alt,
        )
      : Cesium.Cartographic.ZERO;
  }

  /**
   * 拾取位置点
   *
   * @param {Object} px 屏幕坐标
   *
   * @return {Object} Cartesian3 三维坐标
   */
  getCatesian3FromPX(px) {
    if (this._viewer && px) {
      return GISTool.getCartesian(this._viewer.scene, px);
    }
  }

  /**
   * 获取84坐标的距离
   * @param {*} positions
   */
  getPositionDistance(positions) {
    let distance = 0;
    for (let i = 0; i < positions.length - 1; i++) {
      let point1cartographic = this.transformWGS84ToCartographic(positions[i]);
      let point2cartographic = this.transformWGS84ToCartographic(
        positions[i + 1],
      );
      let geodesic = new Cesium.EllipsoidGeodesic();
      geodesic.setEndPoints(point1cartographic, point2cartographic);
      let s = geodesic.surfaceDistance;
      s = Math.sqrt(
        Math.pow(s, 2) +
          Math.pow(point2cartographic.height - point1cartographic.height, 2),
      );
      distance = distance + s;
    }
    return distance.toFixed(3);
  }

  /**
   * 计算一组坐标组成多边形的面积
   * @param {*} positions
   */
  getPositionsArea(positions) {
    let result = 0;
    if (positions) {
      let h = 0;
      let ellipsoid = Cesium.Ellipsoid.WGS84;
      positions.push(positions[0]);
      for (let i = 1; i < positions.length; i++) {
        let oel = ellipsoid.cartographicToCartesian(
          this.transformWGS84ToCartographic(positions[i - 1]),
        );
        let el = ellipsoid.cartographicToCartesian(
          this.transformWGS84ToCartographic(positions[i]),
        );
        h += oel.x * el.y - el.x * oel.y;
      }
      result = Math.abs(h).toFixed(2);
    }
    return result;
  }

  /**
   * 测距
   * @param {*} options
   */
  drawLineMeasureGraphics(options = {}) {
    if (this._viewer && options) {
      let positions = [],
        _lineEntity = new Cesium.Entity(),
        $this = this,
        lineObj,
        lineID = uuidv4();

      // left
      let isDrawing = false;
      this.handlers_.setInputAction(function (movement) {
        if (!isDrawing) {
          isDrawing = true;
        }
        let cartesian = $this.getCatesian3FromPX(movement.position);
        let feature = $this._viewer.scene.pick(movement.position);
        if (
          feature &&
          feature.primitive instanceof Cesium.PointPrimitive &&
          feature.id instanceof Cesium.Entity
        ) {
          let ID = feature.id.id;
          let featureID = ID.split("-&ZYWL&-")[0];
          let index = Number(ID.split("-&ZYWL&-")[2]);
          if (featureID === lineID && index === positions.length - 1) {
            if (positions.length >= 2) {
              isDrawing = false;
              positions.splice(positions.length - 1, 1);
              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.LEFT_CLICK,
              );
              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.MOUSE_MOVE,
              );
              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.RIGHT_CLICK,
              );
              $this.handlers_.destroy();
              $this.handlers_ = undefined;
              if (typeof options.callback === "function") {
                options.callback(
                  $this.transformCartesianArrayToWGS84Array(positions),
                  lineObj,
                );
              }
              $this.handlers_ = new Cesium.ScreenSpaceEventHandler(
                $this._viewer.scene.canvas,
              );
              $this.drawLineMeasureGraphics(options);
            }
            return;
          }
        }
        if (cartesian) {
          if (positions.length === 0) {
          } else {
            positions.splice(positions.length - 1, 1);
          }
          positions.push(cartesian.clone());
          _addInfoPoint(lineID, cartesian, options, positions.length);
          positions.push(cartesian);
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

      this.handlers_.setInputAction(function (movement) {
        if (!isDrawing) {
          return;
        }
        let cartesian = $this.getCatesian3FromPX(movement.endPosition);
        if (cartesian && positions.length >= 2) {
          positions[positions.length - 1] = cartesian;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // right
      this.handlers_.setInputAction(function (movement) {
        isDrawing = false;
        let cartesian = $this.getCatesian3FromPX(movement.position);
        let feature = $this._viewer.scene.pick(movement.position);
        if (
          feature &&
          feature.primitive instanceof Cesium.PointPrimitive &&
          feature.id instanceof Cesium.Entity
        ) {
          let ID = feature.id.id;
          let featureID = ID.split("-&ZYWL&-")[0];
          let index = Number(ID.split("-&ZYWL&-")[2]);
          if (featureID === lineID && index === positions.length - 1) {
            if (positions.length >= 2) {
              positions.splice(positions.length - 1, 1);
            }
          }
        } else {
          if (cartesian) {
            if (positions.length === 0) {
            } else {
              positions.splice(positions.length - 1, 1);
              positions.push(cartesian.clone());
              // 添加量测信息点
              _addInfoPoint(lineID, cartesian, options, positions.length);
            }
          }
        }
        $this.handlers_.removeInputAction(
          Cesium.ScreenSpaceEventType.LEFT_CLICK,
        );
        $this.handlers_.removeInputAction(
          Cesium.ScreenSpaceEventType.MOUSE_MOVE,
        );
        $this.handlers_.removeInputAction(
          Cesium.ScreenSpaceEventType.RIGHT_CLICK,
        );
        $this.handlers_.destroy();
        $this.handlers_ = undefined;
        // $this._viewer.container.style.cursor = "default";
        if (typeof options.callback === "function") {
          options.callback(
            $this.transformCartesianArrayToWGS84Array(positions),
            lineObj,
          );
        }
        $this.handlers_ = new Cesium.ScreenSpaceEventHandler(
          $this._viewer.scene.canvas,
        );
        $this.drawLineMeasureGraphics(options);
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

      _lineEntity.polyline = {
        width: options.width || 3,
        material: options.material || Cesium.Color.BLUE.withAlpha(0.8),
        clampToGround: options.clampToGround || true,
      };
      _lineEntity.polyline.positions = new Cesium.CallbackProperty(function () {
        return positions;
      }, false);

      lineObj = this._drawLayer.entities.add(_lineEntity);

      //添加坐标点
      function _addInfoPoint(ID, position, options, index) {
        var _labelEntity = new Cesium.Entity({
          id: ID + "-&ZYWL&-LineMeasureGraphicsLabel-&ZYWL&-" + index,
        });
        _labelEntity.position = position;
        _labelEntity.point = {
          pixelSize: 8,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          color: options.pointMaterial || Cesium.Color.BLUE.withAlpha(0.8),
          outlineColor:
            options.pointoutlineMaterial || Cesium.Color.BLUE.withAlpha(0.8),
          outlineWidth: options.outlineWidth || 3,
        };
        let distance =
          $this.getPositionDistance(
            $this.transformCartesianArrayToWGS84Array(positions),
          ) * 1;
        if (distance > 1000) {
          distance = (distance / 1000.0).toFixed(1) + "km";
        } else {
          distance = distance.toFixed(1) + "m";
        }
        if (index === 1) {
          distance = "起点";
        }
        _labelEntity.label = {
          text: distance,
          show: true,
          showBackground: true,
          backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
          font: "12px sans-serif", ///"14px monospace",
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          pixelOffset: new Cesium.Cartesian2(10, 0), //left top
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
        };

        $this._drawLayer.entities.add(_labelEntity);
      }
    }
  }

  /**
   * 测面积
   * @param {*} options
   */
  drawAreaMeasureGraphics(options = {}) {
    if (this._viewer && options) {
      let $this = this;
      let _positions = [];
      let _outlinePositions = [];
      let _polygon = new Cesium.PolygonHierarchy(_positions);
      let areaID = uuidv4();
      let _polygonPrimitive = null;
      let _polylinePrimitive = null;
      const appearance = new Cesium.MaterialAppearance({
        flat: true,
        material: new Cesium.Material({
          fabric: {
            type: "Color",
            uniforms: {
              color: Cesium.Color.fromAlpha(
                options?.material ?? Cesium.Color.BLUE,
                0.3,
              ),
            },
          },
        }),
      });
      const outlineAppearance = new Cesium.PolylineMaterialAppearance({
        material: new Cesium.Material({
          fabric: {
            type: "Color",
            uniforms: {
              color: options?.material ?? Cesium.Color.BLUE,
            },
          },
        }),
      });
      let isDrawing = false;
      this.handlers_.setInputAction(function (movement) {
        if (!isDrawing) {
          isDrawing = true;
          if (window.isStartBoxSelection) {
            if (_polygonPrimitive) {
              $this._viewer.scene.primitives.remove(_polygonPrimitive);
            }
            if (_polylinePrimitive) {
              $this._viewer.scene.primitives.remove(_polylinePrimitive);
            }
            _positions = [];
            _outlinePositions = [];
            _polygon = new Cesium.PolygonHierarchy(_positions);
            _polygonPrimitive = null;
            _polylinePrimitive = null;
          }
        }
        const position = $this.getCatesian3FromPX(movement.position);
        if (!position) {
          return;
        }
        const feature = $this._viewer.scene.pick(movement.position);
        if (
          feature &&
          feature.primitive instanceof Cesium.PointPrimitive &&
          feature.id instanceof Cesium.Entity
        ) {
          let ID = feature.id.id;
          let featureID = ID.split("-&ZYWL&-")[0];
          let index = Number(ID.split("-&ZYWL&-")[2]);
          if (
            featureID === areaID &&
            (index === _positions.length - 1 || index === 1)
          ) {
            if (_positions.length >= 3) {
              isDrawing = false;

              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.LEFT_CLICK,
              );
              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.MOUSE_MOVE,
              );
              $this.handlers_.removeInputAction(
                Cesium.ScreenSpaceEventType.RIGHT_CLICK,
              );
              // $this.handlers_.destroy();
              // $this.handlers_ = undefined;

              let deleteIndex = _positions.length - 1;
              _positions.splice(deleteIndex, 1, _positions[0]);
              _polygon.positions = _positions;
              _outlinePositions = _positions.map((value) => {
                return value;
              });
              _outlinePositions.push(_outlinePositions[0]);
              reDrawArea();

              _addInfoPoint(
                areaID,
                position.clone(),
                options,
                _positions.length,
                true,
              );
              if (typeof options.callback === "function") {
                options.callback(
                  $this.transformCartesianArrayToWGS84Array(_outlinePositions),
                );
              }
              $this.drawAreaMeasureGraphics(options);
            }
            return;
          }
        }

        if (_positions.length === 0) {
          _positions.push(position.clone());
        } else {
          let deleteIndex = _positions.length - 1;
          _positions.splice(deleteIndex, 1, position.clone());
        }
        _positions.push(position.clone());
        _polygon.positions = _positions;
        _outlinePositions = _positions.map((value) => {
          return value;
        });
        _outlinePositions.push(_outlinePositions[0]);
        reDrawArea();

        _addInfoPoint(areaID, position, options, _positions.length - 1, false);
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // mouse
      this.handlers_.setInputAction(function (movement) {
        if (!isDrawing) {
          return;
        }
        const position = $this.getCatesian3FromPX(movement.endPosition);
        if (!position) {
          return;
        }
        if (!_positions.length) {
          return;
        }
        _positions[_positions.length - 1] = position;
        _polygon.positions = _positions;
        _outlinePositions = _positions.map((value) => {
          return value;
        });
        _outlinePositions.push(_outlinePositions[0]);
        reDrawArea();
        const point = $this._drawLayer.entities.getById(
          areaID + "-&ZYWL&-AreaMeasureGraphicsLabel-&ZYWL&-1",
        );
        if (point) {
          let area =
            $this.getPositionsArea(
              $this.transformCartesianArrayToWGS84Array(_outlinePositions),
            ) * 1;
          if (area > 1000000.0) {
            area = (area / 1000000.0).toFixed(1) + "k㎡";
          } else {
            area = area.toFixed(1) + "㎡";
          }
          point.label.text = area;
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      // right
      this.handlers_.setInputAction(function (movement) {
        if (window.isStartBoxSelection) {
          if (isDrawing) {
            isDrawing = false;
            let deleteIndex = _positions.length - 1;
            _positions.splice(deleteIndex, 1);
            _polygon.positions = _positions;
            _outlinePositions = _positions.map((value) => {
              return value;
            });
            _outlinePositions.push(_outlinePositions[0]);
            reDrawArea();
            if (typeof options.callback === "function") {
              options.callback(
                $this.transformCartesianArrayToWGS84Array(_outlinePositions),
              );
            }
          }
        }
      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

      function reDrawArea() {
        if (_polygonPrimitive) {
          $this._viewer.scene.primitives.remove(_polygonPrimitive);
        }
        if (_polylinePrimitive) {
          $this._viewer.scene.primitives.remove(_polylinePrimitive);
        }
        const polygonGeometryInstance = new Cesium.GeometryInstance({
          geometry: new Cesium.PolygonGeometry({
            polygonHierarchy: _polygon,
            perPositionHeight: true,
          }),
        });
        const clampToGround = options?.clampToGround ?? true;
        const width = options?.width ?? 3;
        if (clampToGround) {
          _polygonPrimitive = $this._viewer.scene.primitives.add(
            new Cesium.GroundPrimitive({
              geometryInstances: polygonGeometryInstance,
              appearance: appearance,
              asynchronous: false,
              releaseGeometryInstances: false,
              classificationType: Cesium.ClassificationType.BOTH,
            }),
          );
          _polylinePrimitive = $this._viewer.scene.primitives.add(
            new Cesium.GroundPolylinePrimitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.GroundPolylineGeometry({
                  positions: _outlinePositions,
                  width: width,
                }),
              }),
              appearance: outlineAppearance,
              asynchronous: false,
              releaseGeometryInstances: false,
              classificationType: Cesium.ClassificationType.BOTH,
            }),
          );
        } else {
          _polygonPrimitive = $this._viewer.scene.primitives.add(
            new Cesium.Primitive({
              geometryInstances: polygonGeometryInstance,
              appearance: appearance,
              asynchronous: false,
              releaseGeometryInstances: false,
            }),
          );
          _polylinePrimitive = $this._viewer.scene.primitives.add(
            new Cesium.Primitive({
              geometryInstances: new Cesium.GeometryInstance({
                geometry: new Cesium.PolylineGeometry({
                  positions: _outlinePositions,
                  width: width,
                }),
              }),
              appearance: outlineAppearance,
              asynchronous: false,
              releaseGeometryInstances: false,
            }),
          );
        }
        $this.AreaMap.set(areaID, {
          polygonPrimitive: _polygonPrimitive,
          polylinePrimitive: _polylinePrimitive,
        });
      }

      function _addInfoPoint(ID, position, options, index, isLastPoint) {
        if (window.isStartBoxSelection) {
          return;
        }
        var _labelEntity = new Cesium.Entity({
          id: ID + "-&ZYWL&-AreaMeasureGraphicsLabel-&ZYWL&-" + index,
          position: position,
        });
        _labelEntity.point = {
          pixelSize: 8,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          color: options.pointMaterial || Cesium.Color.BLUE.withAlpha(0.8),
          outlineColor:
            options.pointoutlineMaterial || Cesium.Color.BLUE.withAlpha(0.8),
          outlineWidth: options.outlineWidth || 3,
        };
        // if (!isLastPoint) {
        if (index !== 1) {
        } else {
          let area = 0.0 + "平方米";
          _labelEntity.label = {
            text: area,
            show: true,
            showBackground: true,
            backgroundColor: Cesium.Color.BLACK.withAlpha(0.9),
            font: "12px sans-serif",
            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            pixelOffset: new Cesium.Cartesian2(10, 0), //left top
            disableDepthTestDistance: Number.POSITIVE_INFINITY,
            heightReference: options.clampToGround
              ? Cesium.HeightReference.CLAMP_TO_GROUND
              : Cesium.HeightReference.NONE,
          };
        }
        $this._drawLayer.entities.add(_labelEntity);
      }
    }
  }

  /**
   * 画三角量测
   * @param {*} options
   */
  drawTrianglesMeasureGraphics(options = {}) {
    options.style = options.style || {
      width: 3,
      material: Cesium.Color.BLUE.withAlpha(0.5),
    };
    if (this._viewer && options) {
      var _trianglesEntity = new Cesium.Entity(),
        _verticalEntity = new Cesium.Entity(),
        _horizontalEntity = new Cesium.Entity(),
        _positions = [],
        _verticalPositions = [],
        _horizontalPositions = [],
        $this = this,
        _handler = new Cesium.ScreenSpaceEventHandler(
          this._viewer.scene.canvas,
        ),
        _isStartDraw = false;

      function _computesHorizontalLine(positions) {
        if (!positions.length) {
          _verticalPositions = [];
          _horizontalPositions = [];
        } else {
          let position1 = GISTool.transformCartographic(positions[0]);
          let position2 = GISTool.transformCartographic(positions[1]);
          let position3;
          let minPosition;
          let midPosition;
          let maxPosition;
          if (position1.height > position2.height) {
            position3 = GISTool.deepCloneValue(position2);
            position3.height = position1.height;

            minPosition = GISTool.transformCartesian3(position2);
            maxPosition = GISTool.transformCartesian3(position1);
          } else {
            position3 = GISTool.deepCloneValue(position1);
            position3.height = position2.height;

            minPosition = GISTool.transformCartesian3(position1);
            maxPosition = GISTool.transformCartesian3(position2);
          }
          midPosition = GISTool.transformCartesian3(position3);
          _verticalPositions = [midPosition, minPosition];
          _horizontalPositions = [midPosition, maxPosition];
        }
      }

      // left
      _handler.setInputAction(function (movement) {
        const position = $this.getCatesian3FromPX(movement.position);
        if (!position && !position.z) {
          return false;
        }
        if (_positions.length && !_isStartDraw) {
          _isStartDraw = true;
          _positions = [];
          _computesHorizontalLine(_positions);
        }

        if (_positions.length === 0) {
          _isStartDraw = true;
          _positions = [
            GISTool.deepCloneValue(position),
            GISTool.deepCloneValue(position),
          ];
          _computesHorizontalLine(_positions);
        } else {
          _isStartDraw = false;
          if (typeof options.callback === "function") {
            options.callback({
              triangles:
                Cesium.Cartesian3.distance(
                  _positions[0],
                  _positions[1],
                ).toFixed(2) * 1,
              vertical:
                Cesium.Cartesian3.distance(
                  _verticalPositions[0],
                  _verticalPositions[1],
                ).toFixed(2) * 1,
              horizontal:
                Cesium.Cartesian3.distance(
                  _horizontalPositions[0],
                  _horizontalPositions[1],
                ).toFixed(2) * 1,
            });
          }
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // mouse
      _handler.setInputAction(function (movement) {
        if (_isStartDraw) {
          const position = $this.getCatesian3FromPX(movement.endPosition);
          if (position && _positions.length) {
            _positions[1] = GISTool.deepCloneValue(position);
            _computesHorizontalLine(_positions);
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

      //两点直线距离
      _trianglesEntity.polyline = {
        positions: new Cesium.CallbackProperty(() => {
          return _positions;
        }, false),
        width: 4,
        material: Cesium.Color.fromCssColorString("#00C8DF"),
      };
      _trianglesEntity.position = new Cesium.CallbackProperty(() => {
        if (_positions.length === 2) {
          return Cesium.Cartesian3.midpoint(
            _positions[0],
            _positions[1],
            new Cesium.Cartesian3(),
          );
        }
        return _positions[0];
      }, false);
      _trianglesEntity.label = {
        text: new Cesium.CallbackProperty(() => {
          if (_positions.length === 2) {
            return (
              Cesium.Cartesian3.distance(_positions[0], _positions[1]).toFixed(
                2,
              ) + "米"
            );
          }
          return "";
        }, false),
        show: true,
        showBackground: true,
        font: "12px sans-serif",
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        pixelOffset: new Cesium.Cartesian2(0, 0), //left top
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      };
      //两点垂直距离
      _verticalEntity.polyline = {
        positions: new Cesium.CallbackProperty(() => {
          return _verticalPositions;
        }, false),
        width: 4,
        material: Cesium.Color.fromCssColorString("#00C8DF"),
      };
      _verticalEntity.position = new Cesium.CallbackProperty(() => {
        if (_verticalPositions.length === 2) {
          return Cesium.Cartesian3.midpoint(
            _verticalPositions[0],
            _verticalPositions[1],
            new Cesium.Cartesian3(),
          );
        }
        return _verticalPositions[0];
      }, false);
      _verticalEntity.label = {
        text: new Cesium.CallbackProperty(() => {
          if (_verticalPositions.length === 2) {
            return (
              Cesium.Cartesian3.distance(
                _verticalPositions[0],
                _verticalPositions[1],
              ).toFixed(2) + "米"
            );
          }
          return "";
        }, false),
        show: true,
        showBackground: true,
        font: "12px sans-serif",
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        pixelOffset: new Cesium.Cartesian2(0, 0), //left top
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      };
      //两点水平距离
      _horizontalEntity.polyline = {
        positions: new Cesium.CallbackProperty(() => {
          return _horizontalPositions;
        }, false),
        width: 4,
        material: Cesium.Color.fromCssColorString("#00C8DF"),
      };
      _horizontalEntity.position = new Cesium.CallbackProperty(() => {
        if (_horizontalPositions.length === 2) {
          return Cesium.Cartesian3.midpoint(
            _horizontalPositions[0],
            _horizontalPositions[1],
            new Cesium.Cartesian3(),
          );
        }
        return _horizontalPositions[1];
      }, false);
      _horizontalEntity.label = {
        text: new Cesium.CallbackProperty(() => {
          if (_horizontalPositions.length === 2) {
            return (
              Cesium.Cartesian3.distance(
                _horizontalPositions[0],
                _horizontalPositions[1],
              ).toFixed(2) + "米"
            );
          }
          return "";
        }, false),
        show: true,
        showBackground: true,
        font: "12px sans-serif",
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        pixelOffset: new Cesium.Cartesian2(0, 0), //left top
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
      };
      this._drawLayer.entities.add(_horizontalEntity);
      this._drawLayer.entities.add(_verticalEntity);
      this._drawLayer.entities.add(_trianglesEntity);
    }
  }

  /**
   * 剖切面测量
   * @param {*} options
   */
  drawSectionalMeasureGraphics(options = {}) {
    if (this._viewer && options) {
      var _sectionalEntity = new Cesium.Entity(),
        _positions = [],
        $this = this,
        _handler = new Cesium.ScreenSpaceEventHandler(
          this._viewer.scene.canvas,
        ),
        _isStartDraw = false;

      function _computesSectional(positions) {
        if (positions.length === 2) {
          const distance = Cesium.Cartesian3.distance(
            positions[0],
            positions[1],
          );
          const unit = options?.unit ?? 1;
          const count = distance / unit;
          let sectionalPositions = [];
          for (let i = 0; i < count; i++) {
            let position = Cesium.Cartesian3.lerp(
              positions[0],
              positions[1],
              i / count,
              new Cesium.Cartesian3(),
            );
            sectionalPositions.push(position);
          }
          if (sectionalPositions.length) {
            $this._viewer.scene
              .clampToHeightMostDetailed(sectionalPositions)
              .then((cartesian3s) => {
                if (typeof options.callback === "function") {
                  options.callback(
                    cartesian3s.map((cartesian3) => {
                      return GISTool.transformCoordinate(cartesian3);
                    }),
                  );
                }
              });
          }
        }
      }

      // left
      _handler.setInputAction((movement) => {
        let position = this.getCatesian3FromPX(movement.position);
        if (!position && !position.z) {
          return false;
        }
        Cesium.sampleTerrain(
          this._viewer.scene.terrainProvider,
          window.terrainMaximumLevel,
          [GISTool.transformCartographic(position)],
        ).then((cartographics) => {
          position = GISTool.transformCartesian3(cartographics[0]);
          if (_positions.length && !_isStartDraw) {
            _isStartDraw = true;
            _positions = [];
          }
          if (_positions.length === 0) {
            _isStartDraw = true;
            _positions = [
              GISTool.deepCloneValue(position),
              GISTool.deepCloneValue(position),
            ];
          } else {
            _isStartDraw = false;
            _computesSectional(_positions);
          }
        });
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
      // mouse
      _handler.setInputAction((movement) => {
        if (_isStartDraw) {
          let position = $this.getCatesian3FromPX(movement.endPosition);
          if (position && _positions.length) {
            Cesium.sampleTerrain(
              this._viewer.scene.terrainProvider,
              window.terrainMaximumLevel,
              [GISTool.transformCartographic(position)],
            ).then((cartographics) => {
              position = GISTool.transformCartesian3(cartographics[0]);
              _positions[1] = GISTool.deepCloneValue(position);
            });
          }
        }
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      //两点直线距离
      _sectionalEntity.polyline = {
        positions: new Cesium.CallbackProperty(() => {
          return _positions;
        }, false),
        width: 4,
        material: Cesium.Color.fromCssColorString("#00C8DF"),
        clampToGround: true,
      };

      this._drawLayer.entities.add(_sectionalEntity);
    }
  }

  clear() {
    for (const value of this.AreaMap.values()) {
      if (value?.polygonPrimitive) {
        this._viewer.scene.primitives.remove(value?.polygonPrimitive);
      }
      if (value?.polylinePrimitive) {
        this._viewer.scene.primitives.remove(value?.polylinePrimitive);
      }
    }
    this.AreaMap.clear();
  }
}

export default MeasureTool;
