import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
import _extends from 'babel-runtime/helpers/extends';
/**
 * @文件说明: Draw.Modes.Ellipse 绘制“椭圆”模式
 * @创建人: pjtools@vip.qq.com
 * @创建时间: 2020-06-03 11:58:29
 */

import assign from 'lodash/assign';
import round from 'lodash/round';
import Constants from '../constants';
import { defaultDrawSetupMethodsSetup } from './point';
import { calculatePolygonArea } from './polygon';
import CircleMode from './circle';
import { isEmpty, isNumeric } from '../../../../_util/methods-util';

var DEFAULT_CURSOR_OPTIONS = {
  cursor: 'default',
  icon: 'highlight',
  content: '单击确定圆心，ESC键取消',
  clicked: '再次单击，绘制结束'
};

// 计算当前绘制Ellipse椭圆要素的面积与周长
export var calculateEllipseArea = function calculateEllipseArea(context, coordinates, xradius, yradius) {
  var measure = {};
  // 计算Polygon的面积和周长
  var polygonMeasure = calculatePolygonArea(context, coordinates);
  if (polygonMeasure && polygonMeasure.measure) {
    measure = _extends({}, polygonMeasure.measure);
  }
  // 追加椭圆的长轴半径
  measure.xradius = {};
  measure.xradius.radius = xradius < 1 ? xradius * 1000 : xradius;
  measure.xradius.round = round(measure.xradius.radius, 2);
  measure.xradius.unit = xradius < 1 ? 'm' : 'km';
  measure.xradius.unitCN = xradius < 1 ? '米' : '公里';
  // 追加椭圆的短轴半径
  measure.yradius = {};
  measure.yradius.radius = yradius < 1 ? yradius * 1000 : yradius;
  measure.yradius.round = round(measure.yradius.radius, 2);
  measure.yradius.unit = yradius < 1 ? 'm' : 'km';
  measure.yradius.unitCN = yradius < 1 ? '米' : '公里';

  return {
    measure: measure
  };
};

var EllipseMode = {};

// Mode模式的注册 - 激活入口
EllipseMode.onSetup = function () {
  var _this = this;

  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

  // 合并绘制Ellipse模式的光标
  var cursorOptions = assign({}, DEFAULT_CURSOR_OPTIONS, options && options.cursor || {});
  options && (options.cursor = cursorOptions);
  // 执行默认初始化
  defaultDrawSetupMethodsSetup(this, options.cursor);
  // 判定是否开启设定的长轴半径模式
  options.radius = !isEmpty(options.radius) && isNumeric(options.radius) ? Number(options.radius) : null;
  options.radius = options.radius && options.radius > 0 ? options.radius : null;
  // 设置椭圆的偏心率（0：表示椭圆短轴越长；1：表示椭圆短轴越短）
  options.eccentricity = !isEmpty(options.eccentricity) && isNumeric(options.eccentricity) ? Number(options.eccentricity) : 0.8;
  options.eccentricity = options.eccentricity < 0 ? 0 : options.eccentricity >= 1 ? 0.99 : options.eccentricity;

  var renderRequest = void 0;
  return {
    options: options,
    // 椭圆节点数
    divisions: 99,
    // 当前单击时间戳
    clickTime: null,
    // 当前单击的坐标点
    clickCoordinates: null,
    // MouseMove事件的节流刷新
    handleThrottleMouseMove: function handleThrottleMouseMove(state, e) {
      if (!renderRequest) {
        renderRequest = requestAnimationFrame(function () {
          renderRequest = null;
          _this.throttleMouseMove.call(_this, state, e);
        });
      }
    }
  };
};

// 触发已绘制的所有Feature矢量要素对象进行显示渲染
EllipseMode.toDisplayFeatures = CircleMode.toDisplayFeatures;

// Mode模式 - 取消释放
EllipseMode.onStop = CircleMode.onStop;

// 触发删除选中的Feature矢量要素
EllipseMode.onTrash = CircleMode.onTrash;

// 触发Tap/Click时的响应事件
EllipseMode.onTap = EllipseMode.onClick = CircleMode.onClick;

// 触发MouseMove时的响应事件
EllipseMode.onMouseMove = function (state, e) {
  state.handleThrottleMouseMove && state.handleThrottleMouseMove(state, e);
};

// 触发键盘KeyUp时的响应事件
EllipseMode.onKeyUp = CircleMode.onKeyUp;

// Mode模式 - 绘制完成
EllipseMode.onCompleted = function (geojson) {
  // 计算绘制Ellipse椭圆要素的量算
  var measure = calculateEllipseArea(this, geojson.geometry.coordinates, geojson.properties['draw:xradius'], geojson.properties['draw:yradius']);
  // 驱动事件回调
  this.ctx.api.fire(Constants.events.DRAW_COMPLETE, _extends({
    mode: this.getMode(),
    feature: geojson
  }, measure));
  // 切换到“选取”模式
  this.changeMode(Constants.modes.SELECT, {
    featureIds: [geojson.id]
  });
};

// Mode模式 - 绘制取消
EllipseMode.onCancel = CircleMode.onCancel;

// <自定义函数>初始创建绘制模式的Feature对象
EllipseMode.initStateDrawFeature = function (state) {
  var polygon = this.newFeature({
    geometry: {
      type: Constants.geojsonTypes.POLYGON,
      coordinates: []
    }
  });
  polygon.updateInternalProperty('polygon', Constants.modes.DRAW_ELLIPSE);
  polygon.updateInternalProperty('eccentricity', state.options.eccentricity);
  state.polygon = polygon;
  state.polygon.center = null;
  state.polygon.completed = false;
  this.addFeature(polygon);
  // 创建临时Vertex节点要素对象
  var vertex = this.newFeature({
    geometry: {
      type: Constants.geojsonTypes.MULTI_POINT,
      coordinates: []
    }
  });
  vertex.updateInternalProperty('meta', Constants.meta.VERTEX);
  vertex.updateInternalProperty('pid', state.polygon.id);
  state.vertex = vertex;
  this.addFeature(vertex);
  // 创建临时Move时Line要素对象
  var moveline = this.newFeature({
    geometry: {
      type: Constants.geojsonTypes.LINE_STRING,
      coordinates: []
    }
  });
  moveline.updateInternalProperty('meta', Constants.meta.MOVELINE);
  moveline.updateInternalProperty('pid', state.polygon.id);
  state.moveline = moveline;
  this.addFeature(moveline);
};

// <自定义函数>触发单击地图的任意地方
EllipseMode.clickAnywhere = function (state, e) {
  var coordinates = [e.lngLat.lng, e.lngLat.lat];
  // 重新记录单击时间戳和坐标点
  state.clickTime = new Date().valueOf();
  state.clickCoordinates = coordinates;
  // 判定是否创建椭圆的圆心节点
  if (!state.polygon.center) {
    // 更新添加Vertex节点要素坐标点
    var vertexs = state.vertex.getCoordinates();
    vertexs.push(coordinates);
    state.vertex.setCoordinates(vertexs);
    // 更新Ellipse椭圆要素的属性
    state.polygon.center = coordinates;
    state.polygon.updateInternalProperty('center', coordinates.join(','));
    state.polygon.updateInternalProperty('xradius', 0);
    state.polygon.updateInternalProperty('yradius', 0);

    // 判定是否有设定初始长轴半径模式，则直接绘制完成
    if (state.options.radius !== null) {
      // 根据起点与长轴半径获取要素坐标点
      var ellipse = this.getEllipseByRadius(coordinates, state.options.radius, {
        eccentricity: state.options.eccentricity,
        divisions: state.divisions
      });
      // 更新Ellipse椭圆要素的坐标
      var ellipseCoordinates = [].concat(_toConsumableArray(ellipse.coordinates));
      ellipseCoordinates.splice(ellipseCoordinates.length - 1, 1);
      state.polygon.setCoordinates([ellipseCoordinates]);
      state.polygon.updateInternalProperty('xradius', ellipse.xradius);
      state.polygon.updateInternalProperty('yradius', ellipse.yradius);
      // 结束绘制
      this.doubleClick(state);
    } else {
      // 增加Ellipse椭圆要素的坐标点
      state.polygon.updateCoordinate('0.0', coordinates[0], coordinates[1]);
      // 更新Ellipse椭圆的MoveLine线要素的起始坐标
      state.moveline.setCoordinates([coordinates]);
      // 更新鼠标提示
      state.options.cursor.clicked && this.updateCursor({ content: state.options.cursor.clicked });
      // 触发执行绘制单击时的回调事件
      this.ctx.api.fire(Constants.events.DRAW_CLICK, {
        e: e,
        mode: this.getMode(),
        feature: state.polygon.toGeoJSON(),
        center: state.polygon.center
      });
    }
  } else {
    this.doubleClick(state);
  }
};

// <自定义函数>判定doubleClick时的响应事件
EllipseMode.doubleClick = CircleMode.doubleClick;

// <自定义函数>判定是否为DoubleClick双击事件
EllipseMode.isDoubleClick = CircleMode.isDoubleClick;

// <自定义函数>触发MouseMove事件的节流响应
EllipseMode.throttleMouseMove = function (state, e) {
  if (!state.moveline || !state.polygon.center) {
    return;
  }

  var coordinates = [e.lngLat.lng, e.lngLat.lat];
  // 根据两点获取绘制椭圆的坐标
  var ellipse = this.getEllipseByCoordinates(state.polygon.center, coordinates, {
    eccentricity: state.options.eccentricity,
    divisions: state.divisions
  });
  // 更新临时移动MoveLine要素的坐标
  state.moveline.setCoordinates(ellipse.coordinates);
  // 更新Ellipse椭圆要素的坐标
  var ellipseCoordinates = [].concat(_toConsumableArray(ellipse.coordinates));
  ellipseCoordinates.splice(ellipseCoordinates.length - 1, 1);
  state.polygon.setCoordinates([ellipseCoordinates]);
  state.polygon.updateInternalProperty('xradius', ellipse.xradius);
  state.polygon.updateInternalProperty('yradius', ellipse.yradius);
  // 计算绘制Move的临时Ellipse椭圆要素的量算
  var polygonFeature = state.polygon.toGeoJSON();
  var measure = calculateEllipseArea(this, polygonFeature.geometry.coordinates, ellipse.xradius, ellipse.yradius);
  // 触发执行绘制Move时的回调事件
  this.ctx.api.fire(Constants.events.DRAW_MOUSEMOVE, _extends({
    e: e,
    mode: this.getMode(),
    feature: polygonFeature
  }, measure));
};

// <自定义函数>移除临时移动MoveLine要素和节点要素
EllipseMode.deleteMoveLineAndVertex = CircleMode.deleteMoveLineAndVertex;

// <自定义函数>根据起始点与长轴半径点坐标获取椭圆要素坐标
EllipseMode.getEllipseByCoordinates = function (center, coordinates) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

  var iMapApi = this.ctx.api.iMapApi;
  var turf = iMapApi.exports.turf;
  // 计算长轴距离

  var wgs84Center = iMapApi.toWGS84(center);
  var wgs84Coordinates = iMapApi.toWGS84(coordinates);
  var xradius = Math.sqrt(Math.pow(wgs84Coordinates[0] - wgs84Center[0], 2) + Math.pow(wgs84Coordinates[1] - wgs84Center[1], 2));
  // 转换短轴半径
  var yradius = xradius * Math.sqrt(1 - Math.pow(options.eccentricity, 2));
  // 计算弧度
  var radian = Math.atan2(wgs84Coordinates[1] - wgs84Center[1], wgs84Coordinates[0] - wgs84Center[0]);
  // 生成椭圆的坐标点
  var startCoordinates = [];
  var ellipseCoordinates = [];
  for (var i = 0; i < options.divisions; i++) {
    var angle = i / options.divisions * (Math.PI * 2);
    var cos = Math.cos(radian);
    var sin = Math.sin(radian);
    var tx = xradius * Math.cos(angle);
    var ty = yradius * Math.sin(angle);
    // 围绕椭圆中心旋转点。
    var x = tx * cos - ty * sin + wgs84Center[0];
    var y = tx * sin + ty * cos + wgs84Center[1];
    i === 0 && (startCoordinates = [x, y]);
    ellipseCoordinates.push(iMapApi.fromWGS84([x, y]));
  }
  ellipseCoordinates.push(ellipseCoordinates[0]);
  // 计算长轴距离
  var radius = turf.length(turf.lineString([wgs84Center, startCoordinates]), { units: 'kilometers' });

  return {
    coordinates: ellipseCoordinates,
    xradius: radius,
    yradius: radius * Math.sqrt(1 - Math.pow(options.eccentricity, 2))
  };
};

// <自定义函数>根据起始点与长轴半径获取椭圆要素坐标
EllipseMode.getEllipseByRadius = function (center, radius) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

  var iMapApi = this.ctx.api.iMapApi;
  var turf = iMapApi.exports.turf;
  // 获取长轴半径点

  var feature = turf.destination(iMapApi.toWGS84(center), radius, 0, { units: 'kilometers' });
  var coordinates = iMapApi.fromWGS84(turf.getCoord(feature));
  // 获取椭圆的坐标点
  var ellipse = this.getEllipseByCoordinates(center, coordinates, options);

  return {
    coordinates: ellipse.coordinates,
    xradius: radius,
    yradius: radius * Math.sqrt(1 - Math.pow(options.eccentricity, 2))
  };
};

export default EllipseMode;