import DataUtils from "../utils/DataUtils";
import GeogUtils from "../utils/GeogUtils";
import VerifyUtils from "../utils/VerifyUtils";
import WKTProvider from "../geog/WKTProvider";
import GeoJsonProvider from "../geog/GeoJsonProvider";
import LayerProvider from "../geog/LayerProvider";
import MapProvider from "../geog/MapProvider";
import SimpleMarkerLayer from "../common/SimpleMarkerLayer";
import SimpleLineLayer from "../common/SimpleLineLayer";

/**
 * 编辑提供类
 *
 * @alias EditorProvider
 *
 * @summary <用于编辑管网设施>
 */
export default class EditorProvider {
  /**
   * 构造函数
   * @param {Object} options -图层选项
   */
  constructor(options) {
    /**
     * 地图对象
     * @type {Object}
     */
    this._map = options.map;

    /**
     * 最小缩放层级
     * @type {Number}
     */
    this._minzoom = DataUtils.default(options.minzoom, 10);

    /**
     * 图标(表达式)
     * @type {String|Object}
     */
    this._icon = DataUtils.default(options.icon, undefined);

    /**
     * 线颜色(表达式)
     * @type {String|Object}
     */
    this._lineColor = DataUtils.default(options.lineColor, undefined);

    /**
     * 线宽
     * @type {Number}
     */
    this._lineWidth = DataUtils.default(options.lineWidth, 10.5);

    /** 图层样式 **/
    // 点图标
    this._markerAddIcon = 'editor_add';          // 添加
    this._markerAddSelIcon = 'editor_add-sel';   // 选中添加
    this._markerAddEditIcon = 'editor_add-edit'; // 编辑添加
    this._markerSelIcon = 'editor_sel';   // 选中
    this._markerEditIcon = 'editor_edit'; // 编辑
    this._markerDelIcon = 'editor_del';   // 删除
    this._arrowIcon = 'icon_directionred'; // 方向
    // 线颜色
    this._lineAddColor = '#176BC9'; // 添加
    this._lineSelColor = '#87CEFA'; // 选中
    this._lineDelColor = '#8C8C8C'; // 删除  #DC143C

    /**
     * 编辑日志
     * @summery <[
     *   {index: 1, edit_state: 'add', fid: fid, layer_code: code, type: 'marker', feature: null},
     *   {index: 2, edit_state: 'edit', fid: fid, layer_code: code, type: 'line', feature: null},
     *   {index: 3, edit_state: 'delete', fid: fid, layer_code: code, type: 'line', feature: null},
     * ]>
     */
    this._editingLog = [];
    /**
     * 编辑日志
     * @summery <[
     *   {index: 1, edit_state: 'add', type: 'marker', features: []},
     *   {index: 2, edit_state: 'edit', type: 'line', features: []},
     *   {index: 3, edit_state: 'delete', type: 'line', features: []},
     * ]>
     */
    this._editLog = [];
    // 已编辑的数据
    this._editedData = [];

    /** 要素集 **/
    // 点要素集
    this._pointFC = GeoJsonProvider.getEmptyFC();
    // 线要素集
    this._polylineFC = GeoJsonProvider.getEmptyFC();
    // 线中心点要素集
    this._centerPointFC = GeoJsonProvider.getEmptyFC();

    /** 图层 **/
    this._addedFaciMarkerLayer = null; // 添加的设施点图层
    this._addedMarkerLayer = null;     // 添加的点图层
    this._selectedMarkerLayer = null; // 选中的点图层
    this._editedMarkerLayer = null;   // 编辑的点图层
    this._deletedMarkerLayer = null;  // 删除的点图层

    this._lineCenterMarkerLayer = null;    // 线中心点图层
    this._lineDirectionMarkerLayer = null; // 线方向点图层
    this._addedFaciLineLayer = null; // 添加的设施线图层
    this._addedLineLayer = null;     // 添加的线图层
    this._selectedLineLayer = null;  // 选中的线图层
    this._editedLineLayer = null;    // 编辑的线图层
    this._deletedLineLayer = null;   // 删除的线图层
    // 线图层是否已移动
    this._isAddedLineLayerMoved = false;
    this._isSelectedLineLayerMoved = false;
    this._isEditedLineLayerMoved = false;
    this._isDeletedLineLayerMoved = false;

    // 初始化图层
    this._initLayers();
  }

  /** 公有方法 **/
  /**
   * 设置数据
   * @param {Array} data -GeoJSON要素集合
   */
  setData(data) {
    if (!data ||
        !VerifyUtils.isArray(data) || data.length === 0 ||
        (VerifyUtils.isArray(data) && !VerifyUtils.isGeoJsonFeature(data[0]))) return;

    this._editingLog = [];
    this._editLog = [];
    this._editedData = data;

    // 更新数据
    this._updateData(data);
    // 缩放到要素范围
    this._fitBounds();
  }

  /**
   * 添加数据
   * @param {String} type -编辑类型(add、select、edit、reverse、delete)
   * @param {Object|Array} data -GeoJSON要素/要素集合
   */
  appendData(type, data) {
    let features = null;
    if (VerifyUtils.isArray(data)) {
      if (data.length === 0 || !VerifyUtils.isGeoJsonFeature(data[0])) {
        return;
      }
      features = data;
    } else if (VerifyUtils.isGeoJsonFeature(data)) {
      features = [data];
    }
    if (!features || features.length === 0) return;

    // 添加操作日志
    if (type !== 'select') {
      this._appendLog(type, features);
    }

    if (type !== 'reverse') { // 非反转图形
      // 获取点要素列表
      const pointFeatures = features.filter((fea) => {
        return fea.geometry.type.toLowerCase() === 'point';
      });
      if (pointFeatures.length > 0) {
        // 更新点数据
        this._updateMarkerData(type, pointFeatures);
      }
    }

    // 获取线要素列表
    let lineFeatures = features.filter((fea) => {
      return fea.geometry.type.toLowerCase() === 'linestring' ||
             fea.geometry.type.toLowerCase() === 'multilinestring';
    });
    if (type === 'reverse') {
      // 去除掉添加/反转的数据
      lineFeatures = lineFeatures.filter((fea) => {
        let editState = fea.properties.edit_state;
        return !editState || (
               editState.indexOf('add') < 0 &&
               editState.indexOf('edit-reverse') < 0
              );
      });
    }
    if (lineFeatures.length > 0) {
      // 更新线数据
      this._updateLineData(type, lineFeatures);
    }
  }

  /**
   * 选择数据
   * @param {Object|Array} data -GeoJSON要素/要素集合
   */
  selectData(data) {
    let features = null;

    if (VerifyUtils.isArray(data)) {
      if (data.length === 0 || !VerifyUtils.isGeoJsonFeature(data[0])) {
        return;
      }
      features = data;
    } else if (VerifyUtils.isGeoJsonFeature(data)) {
      features = [data];
    }
    if (!features || features.length === 0) return;

    const editType = 'select';

    let pointFeatures = features.filter((fea) => {
      return fea.geometry.type.toLowerCase() === 'point'
    });
    let lineFeatures = features.filter((fea) => {
      return (
        fea.geometry.type.toLowerCase() === 'linestring' ||
        fea.geometry.type.toLowerCase() === 'multilinestring'
      )
    });

    // 更新点数据源
    if (pointFeatures.length > 0) {
      // 过滤该类型的要素集合
      this._pointFC.features = this._pointFC.features.filter((fea) => {
        return fea.properties.edit_state !== editType;
      });

      this._updateMarkerData(editType, pointFeatures);
    }
    // 更新线数据源
    if (lineFeatures.length > 0) {
      // 过滤该类型的要素集合
      this._polylineFC.features = this._polylineFC.features.filter((fea) => {
        return fea.properties.edit_state !== editType;
      });
      this._centerPointFC.features = this._centerPointFC.features.filter((fea) => {
        return fea.properties.edit_state !== editType;
      });

      this._updateLineData(editType, lineFeatures);
    }

    /*
    if (!VerifyUtils.isGeoJsonFeature(data)) return;

    const editType = 'select';
    const feature = data;

    const geomType = feature.geometry.type.toLowerCase();
    switch (geomType) {
      case 'point': {
        // 过滤该类型的要素集合
        this._pointFC.features = this._pointFC.features.filter((fea) => {
          return fea.properties.edit_state !== editType;
        });
        // 更新点数据
        this._updateMarkerData(editType, [feature]);
        break;
      }
      case 'linestring':
      case 'multilinestring': {
        // 过滤该类型的要素集合
        this._polylineFC.features = this._polylineFC.features.filter((fea) => {
          return fea.properties.edit_state !== editType;
        });
        this._centerPointFC.features = this._centerPointFC.features.filter((fea) => {
          return fea.properties.edit_state !== editType;
        });
        // 更新线数据
        this._updateLineData(editType, [feature]);
        break;
      }
      case 'polygon':
      case 'multipolygon': {
        return;
      }
      default:
        return;
    }
    */
  }

  /**
   * 撤销
   * @param {Function} callback -回调
   */
  undo_old(callback) {
    let log = this._editingLog;
    if (log.length === 0) {
      callback(false, null);
      return;
    }

    // 获取最后一个序号的日志列表
    let currIndex = log[log.length - 1].index;
    let logItems = log.filter((item) => {
      return item.index === currIndex;
    });
    // 去除最后一个序号的日志列表
    this._editingLog = log.filter((item) => {
      return item.index !== currIndex;
    });
    log = this._editingLog;
    const canUndo = log.length > 0;

    let logItem = logItems[0];
    if (logItem.type === 'marker') { // 点图层
      const fc = this._pointFC;

      switch (logItem.edit_state) {
        case 'add': { // 添加
          fc.features = fc.features.filter((fea) => {
            let editState = fea.properties.edit_state;
            let isAddState = editState === 'add' || editState === 'add-select';
            return !isAddState || (isAddState && fea.properties.fid !== logItem.fid);
          });

          // 更新数据源
          this._addedFaciMarkerLayer.setData(fc);
          this._addedMarkerLayer.setData(fc);

          // 回调
          callback(canUndo, null);
          break;
        }
        case 'edit': { // 编辑
          let found = findPrevLogFeatures(logItem, log, fc.features);
          if (!found) {
            // 去除编辑的要素
            fc.features = fc.features.filter((fea) => {
              let isEditState = fea.properties.edit_state.indexOf('edit') === 0;
              return !isEditState ||
                     (isEditState && fea.properties.fid !== logItem.fid);
            });
          }

          // 更新数据源
          this._editedMarkerLayer.setData(fc);
          this._selectedMarkerLayer.setData(fc);
          this._addedFaciMarkerLayer.setData(fc);
          this._addedMarkerLayer.setData(fc);

          // 回调
          let tmpFeas = [];
          if (found) {
            tmpFeas = fc.features.filter((fea) => {
              return fea.properties.fid === logItem.fid;
            });
          }
          callback(canUndo, tmpFeas.length > 0 ? tmpFeas[0] : null);
          break;
        }
        case 'delete': {
          let found = findPrevLogFeatures(logItem, log, fc.features);
          if (!found) {
            // 去除删除的要素
            fc.features = fc.features.filter((fea) => {
              let isDelState = fea.properties.edit_state === 'delete';
              return !isDelState ||
                     (isDelState && fea.properties.fid !== logItem.fid);
            });
          }

          // 更新数据源
          this._deletedMarkerLayer.setData(fc);
          this._editedMarkerLayer.setData(fc);
          this._selectedMarkerLayer.setData(fc);
          this._addedFaciMarkerLayer.setData(fc);
          this._addedMarkerLayer.setData(fc);

          let tmpFeas = [];
          if (found) {
            tmpFeas = fc.features.filter((fea) => {
              return fea.properties.fid === logItem.fid;
            });
          }
          callback(canUndo, tmpFeas.length > 0 ? tmpFeas[0] : null);
          break;
        }
        default:
          break;
      }
    } else if (logItem.type === 'line') { // 线图层
      const fc = this._polylineFC;
      const centerFC = this._centerPointFC;

      switch (logItem.edit_state) {
        case 'add': { // 添加
          fc.features = fc.features.filter((fea) => {
            let editState = fea.properties.edit_state;
            let isAddState = editState === 'add' || editState === 'add-select';

            return !isAddState || (isAddState && fea.properties.fid !== logItem.fid);
          });

          centerFC.features = centerFC.features.filter((fea) => {
            let editState = fea.properties.edit_state;
            let isAddState = editState === 'add' || editState === 'add-select';

            return !isAddState || (isAddState && fea.properties.fid !== logItem.fid);
          });

          // 更新数据源
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          this._lineCenterMarkerLayer.setData(centerFC);

          // 回调
          callback(canUndo, null);
          break;
        }
        case 'edit': { // 编辑
          let found = findPrevLogFeatures(logItem, log, fc.features, centerFC.features);
          if (!found) {
            // 去除编辑的要素
            fc.features = fc.features.filter((fea) => {
              let isEditState = fea.properties.edit_state.indexOf('edit') === 0;
              return !isEditState ||
                     (isEditState && fea.properties.fid !== logItem.fid);
            });

            centerFC.features = centerFC.features.filter((fea) => {
              let isEditState = fea.properties.edit_state.indexOf('edit') === 0;
              return !isEditState ||
                     (isEditState && fea.properties.fid !== logItem.fid);
            });
          }

          // 更新数据源
          this._editedLineLayer.setData(fc);
          this._selectedLineLayer.setData(fc);
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          this._lineCenterMarkerLayer.setData(centerFC);
          this._lineDirectionMarkerLayer.setData(centerFC);

          // 回调
          let tmpFeas = [];
          if (found) {
            tmpFeas = fc.features.filter((fea) => {
              return fea.properties.fid === logItem.fid;
            });
          }
          callback(canUndo, tmpFeas.length > 0 ? tmpFeas[0] : null);
          break;
        }
        case 'delete': { // 删除
          let found = findPrevLogFeatures(logItem, log, fc.features, centerFC.features);
          if (!found) {
            // 去除编辑的要素
            fc.features = fc.features.filter((fea) => {
              let isDelState = fea.properties.edit_state === 'delete';
              return !isDelState ||
                     (isDelState && fea.properties.fid !== logItem.fid);
            });

            centerFC.features = centerFC.features.filter((fea) => {
              let isDelState = fea.properties.edit_state === 'delete';
              return !isDelState ||
                     (isDelState && fea.properties.fid !== logItem.fid);
            });
          }

          // 更新数据源
          this._deletedLineLayer.setData(fc);
          this._editedLineLayer.setData(fc);
          this._selectedLineLayer.setData(fc);
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          this._lineCenterMarkerLayer.setData(centerFC);

          // 回调
          let tmpFeas = [];
          if (found) {
            tmpFeas = fc.features.filter((fea) => {
              return fea.properties.fid === logItem.fid;
            });
          }
          callback(canUndo, tmpFeas.length > 0 ? tmpFeas[0] : null);
          break;
        }
        default:
          break;
      }
    }

    // 处理台账跳转过来的情况
    if (!canUndo && this._editedData.length > 0) {
      this._updateData(this._editedData);
    }

    /**
     * 查找之前的日志项
     * @param {Object} item -当前日志项
     * @param {Array} log -日志列表
     * @param {Array} features -要素集合
     *
     * @returns {Boolean}
     */
    function findPrevLogFeatures(item, log, features, centerFeatures = null) {
      // 查找日志项
      for (let i = log.length - 1; i >= 0; i--) {
        if (log[i].fid === item.fid) {
          let prevFea = log[i].feature;

          // 处理要素集合为空的情况
          if (features.length === 0) {
            features.push(prevFea);
          }
          if (centerFeatures && centerFeatures.length === 0) {
            // 计算线中点
            let center = GeogUtils.calcCenter(prevFea);

            let centerFea = GeoJsonProvider.getPointFeature(center, prevFea.properties);
            centerFeatures.push(centerFea);
          }

          // 查找要素
          let itemFeas = features.filter((fea) => {
            return fea.properties.fid === item.fid;
          });
          if (itemFeas.length === 0) {
            return false;
          }

          // 更新要素坐标、属性
          itemFeas.forEach((fea) => {
            fea.geometry.coordinates = prevFea.geometry.coordinates;
            fea.properties = prevFea.properties;
          });

          // 更新线中点的编辑状态
          if (centerFeatures && centerFeatures.length > 0) {
            let tmpFeas = centerFeatures.filter((fea) => {
              return fea.properties.fid === item.fid;
            });
            tmpFeas.forEach((fea) => {
              fea.properties.edit_state = prevFea.properties.edit_state;
            });
          }

          return true;
        }
      } // end of for (...)

      return false;
    }
  }

  /**
   * 撤销
   * @param {Function} callback -回调
   */
  undo(callback) {
    let editLog = this._editLog;
    if (editLog.length === 0) {
      callback(false, null);
      return;
    }

    // 获取最后一个序号的日志列表
    let currIndex = editLog[editLog.length - 1].index;
    let logItems = editLog.filter(item => item.index === currIndex);
    let logItem = logItems[0];

    // 去除最后一个序号的日志列表
    this._editLog = editLog.filter(item => item.index !== currIndex);
    editLog = this._editLog;
    const canUndo = editLog.length > 0;

    if (logItem.type === 'marker') { // 点图层
      const fc = this._pointFC;

      switch (logItem.edit_state) {
        case 'add': { // 添加
          // 过滤添加的点要素
          fc.features = fc.features.filter((feature) => {
            let isAddState = (
              feature.properties.edit_state === 'add' ||
              feature.properties.edit_state === 'add-select'
            );

            return (
              !isAddState ||
              (isAddState && !logItem.features.some((itemFea) => {
                return itemFea.properties.fid === feature.properties.fid
              }))
            );
          });

          // 更新数据源
          this._addedFaciMarkerLayer.setData(fc);
          this._addedMarkerLayer.setData(fc);

          // 回调
          callback(canUndo, null);
          break;
        }
        case 'edit':
        case 'delete': { // 编辑/删除
          let resFeas = [];
          // 查找之前日志要素
          const found = findPrevFeatures(logItem, editLog, fc.features);
          if (found) {
            resFeas = fc.features.filter((feature) => {
              return logItem.features.some((itemFea) => {
                return itemFea.properties.fid = feature.properties.fid
              })
            });
          } else {
            const state = logItem.edit_state;
            // 过滤编辑/删除的要素
            fc.features = fc.features.filter((feature) => {
              let isEditState = feature.properties.edit_state.indexOf(state) === 0;

              return (
                !isEditState ||
                (isEditState && !logItem.features.some((itemFea) => {
                  return itemFea.properties.fid === feature.properties.fid
                }))
              );
            });
          }

          // 更新数据源
          this._deletedMarkerLayer.setData(fc);
          this._editedMarkerLayer.setData(fc);
          this._selectedMarkerLayer.setData(fc);
          this._addedFaciMarkerLayer.setData(fc);
          this._addedMarkerLayer.setData(fc);

          // 回调
          callback(canUndo, resFeas.length > 0 ? resFeas[0] : null);
          break;
        }
        default:
          break;
      }
    } else if (logItem.type === 'line') { // 线图层
      const fc = this._polylineFC;
      const centerFC = this._centerPointFC;

      switch (logItem.edit_state) {
        case 'add': { // 添加
          // 过滤添加的线要素
          fc.features = fc.features.filter((feature) => {
            let isAddState = (
              feature.properties.edit_state === 'add' ||
              feature.properties.edit_state === 'add-select'
            );

            return (
              !isAddState ||
              (isAddState && !logItem.features.some((itemFea) => {
                return itemFea.properties.fid === feature.properties.fid
              }))
            );
          });
          // 过滤添加的线中点要素
          centerFC.features = centerFC.features.filter((feature) => {
            let isAddState = (
              feature.properties.edit_state === 'add' ||
              feature.properties.edit_state === 'add-select'
            );

            return (
              !isAddState ||
              (isAddState && !logItem.features.some((itemFea) => {
                return itemFea.properties.fid === feature.properties.fid
              }))
            );
          });

          // 更新数据源
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          this._lineCenterMarkerLayer.setData(centerFC);

          // 回调
          callback(canUndo, null);
          break;
        }
        case 'edit':
        case 'delete': { // 编辑/删除
          let resFeas = [];
          // 查找之前日志要素
          const found = findPrevFeatures(logItem, editLog, fc.features, centerFC.features);
          if (found) {
            resFeas = fc.features.filter((feature) => {
              return logItem.features.some((itemFea) => {
                return itemFea.properties.fid = feature.properties.fid
              })
            });
          } else {
            const state = logItem.edit_state;
            // 过滤编辑/删除的线要素
            fc.features = fc.features.filter((feature) => {
              let isEditState = feature.properties.edit_state.indexOf(state) === 0;

              return (
                !isEditState ||
                (isEditState && !logItem.features.some((itemFea) => {
                  return itemFea.properties.fid === feature.properties.fid
                }))
              );
            });

            // 过滤编辑/删除的线中点要素
            centerFC.features = centerFC.features.filter((feature) => {
              let isEditState = feature.properties.edit_state.indexOf(state) === 0;

              return (
                !isEditState ||
                (isEditState && !logItem.features.some((itemFea) => {
                  return itemFea.properties.fid === feature.properties.fid
                }))
              );
            });
          }

          // 更新数据源
          this._deletedLineLayer.setData(fc);
          this._editedLineLayer.setData(fc);
          this._selectedLineLayer.setData(fc);
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          this._lineCenterMarkerLayer.setData(centerFC);
          this._lineDirectionMarkerLayer.setData(centerFC);

          // 回调
          callback(canUndo, resFeas.length > 0 ? resFeas[0] : null);
          break;
        }
        default:
          break;
      }
    }

    // 处理台账跳转过来的情况
    if (!canUndo && this._editedData.length > 0) {
      this._updateData(this._editedData);
    }

    /**
     * 查找之前的日志项要素
     * @param {Object} logItem -当前日志项
     * @param {Array} editLog -编辑日志(除去当前日志项)
     * @param {Array} features -要素集合
     * @param {Array} centerFeatures -线终点要素集合
     *
     * @returns {Boolean}
     */
    function findPrevFeatures(logItem, editLog, features, centerFeatures = null) {
      let foundCount = 0;

      for (let i = 0; i < logItem.features.length; i++) {
        const itemFea = logItem.features[i];
        const itemProps = itemFea.properties;

        // 查找日志项
        for (let j = editLog.length - 1; j >= 0; j--) {
          const prevFeas = editLog[j].features.filter((fea) => {
            return fea.properties.fid === itemProps.fid
          });
          if (prevFeas.length === 0) continue;

          let prevFea = prevFeas[0];

          // 处理要素集合为空的情况
          if (features.length === 0) {
            features.push(prevFea);
          }
          if (centerFeatures && centerFeatures.length === 0) {
            // 计算线中点
            let center = GeogUtils.calcCenter(prevFea);

            let centerFea = GeoJsonProvider.getPointFeature(center, prevFea.properties);
            centerFeatures.push(centerFea);
          }

          // 查找要素
          let itemFeas = features.filter((fea) => {
            return fea.properties.fid === itemProps.fid;
          });
          if (itemFeas.length === 0) continue;

          // 更新要素坐标、属性
          itemFeas.forEach((fea) => {
            fea.geometry.coordinates = prevFea.geometry.coordinates;
            fea.properties = prevFea.properties;
          });

          // 更新线中点的编辑状态
          if (centerFeatures && centerFeatures.length > 0) {
            let tmpFeas = centerFeatures.filter((fea) => {
              return fea.properties.fid === itemProps.fid;
            });
            tmpFeas.forEach((fea) => {
              fea.properties.edit_state = prevFea.properties.edit_state;
            });
          }

          foundCount++;
        } // end of for (...)
      };

      return foundCount > 0;
    }
  }

  /**
   * 清除日志
   */
  clearLog() {
    this._editingLog = [];
    this._editLog = [];
  }

  /**
   * 清除选中的数据
   */
  clearSelectedData() {
    // 点数据
    this._clearSelectedMarkerData();

    // 线数据
    this._clearSelectedLineData();
  }

  /**
   * 获取数据
   *
   * @return {Array}
   */
  getData() {
    let data = [];

    // 点要素集
    this._pointFC.features.forEach((fea) => {
      if (fea.properties.edit_state !== 'select') {
        const properties = DataUtils.clone(fea.properties);
        switch (properties.edit_state) {
          case 'add-select':
          case 'add-edit':
          case 'add-edit-select': {
            properties.edit_state = 'add';
            break;
          }
          case 'edit-select': {
            properties.edit_state = 'edit';
            break;
          }
          default:
            break;
        }
        // 获取WKT格式几何图形
        properties.geom = WKTProvider.fromGeometry(fea.geometry);

        data.push(properties);
      }
    });

    // 线要素集
    this._polylineFC.features.forEach((fea) => {
      if (fea.properties.edit_state !== 'select') {
        const properties = DataUtils.clone(fea.properties);
        switch (properties.edit_state) {
          case 'add-select':
          case 'add-edit':
          case 'add-edit-select': {
            properties.edit_state = 'add';
            break;
          }
          case 'edit-select':
          case 'edit-reverse':
          case 'edit-reverse-select': {
            properties.edit_state = 'edit';
            break;
          }
          default:
            break;
        }
        // 获取WKT格式几何图形
        properties.geom = WKTProvider.fromGeometry(fea.geometry);

        data.push(properties);
      }
    });

    return data;
  }

  /**
   * 获取记录要素
   * @param {Object} data -记录对象
   */
  getRecordFeature(data) {
    let fc = null;
    switch (data.layerCode) {
      case 'ditch':
      case 'pipelinerain':
      case 'pipelinewaste':
      case 'pipelineindustry': { // 折线
        fc = this._polylineFC;
        break;
      }
      default: { // 点
        fc = this._pointFC
        break;
      }
    }
    const features = fc.features.filter((fea) => {
      return (
        fea.properties.layer_code === data.layerCode &&
        fea.properties.fid === data.faciId
      )
    });

    return features.length > 0 ? features[0] : null;
  }

  /**
   * 移除所有图层
   */
  removeAllLayers() {
    // 添加的点图层
    if (this._addedMarkerLayer) {
      this._addedFaciMarkerLayer.removeLayer();
      this._addedMarkerLayer.removeLayer();

      this._addedMarkerLayer.removeSource();
    }
    // 编辑的点图层
    if (this._editedMarkerLayer) {
      this._editedMarkerLayer.removeLayer();
      this._editedMarkerLayer.removeSource();
    }
    // 删除的点图层
    if (this._deletedMarkerLayer) {
      this._deletedMarkerLayer.removeLayer();
      this._deletedMarkerLayer.removeSource();
    }

    // 添加的线图层
    if (this._addedLineLayer) {
      this._addedFaciLineLayer.removeLayer();
      this._addedLineLayer.removeLayer();

      this._addedLineLayer.removeSource();
    }
    // 编辑的线图层
    if (this._editedLineLayer) {
      this._editedLineLayer.removeLayer();
      this._editedLineLayer.removeSource();
    }
    // 删除的线图层
    if (this._deletedLineLayer) {
      this._deletedLineLayer.removeLayer();
      this._deletedLineLayer.removeSource();
    }
    // 线中心点图层
    if (this._lineCenterMarkerLayer) {
      this._lineCenterMarkerLayer.removeLayer();
      this._lineCenterMarkerLayer.removeSource();
    }
  }

  /**
   * 绑定单击事件
   * @param {Fcuntion} event -事件
   */
  onClick(event) {
    // 点图层
    this._addedFaciMarkerLayer.onClick(event);
    this._addedMarkerLayer.onClick(event);
    this._selectedMarkerLayer.onClick(event);
    this._editedMarkerLayer.onClick(event);

    // 线图层
    this._addedLineLayer.onClick(event);
    this._selectedLineLayer.onClick(event);
    this._editedLineLayer.onClick(event);
  }

  /**
   * 绑定事件
   * @param {Fcuntion} event -事件
   */
  onEvent(name, event) {
    // 点图层
    this._addedFaciMarkerLayer.onEvent(name, event);
    this._addedMarkerLayer.onEvent(name, event);
    this._editedMarkerLayer.onEvent(name, event);

    // 线图层
    this._addedLineLayer.onEvent(name, event);
    this._editedLineLayer.onEvent(name, event);
  }

  /** 私有方法 **/
  /**
   * 初始化图层
   */
  _initLayers() {
    // 点图层
    this._initMarkerLayer('add');
    this._initMarkerLayer('select');
    this._initMarkerLayer('edit');
    this._initMarkerLayer('delete');
    // 线图层
    this._initLineLayer('add');
    this._initLineLayer('select');
    this._initLineLayer('edit');
    this._initLineLayer('delete');
  }

  /**
   * 初始化点图层
   * @param {String} editType -编辑类型
   */
  _initMarkerLayer(editType) {
    const map = this._map;
    const minZoom = this._minzoom;

    let markerLayer = null;
    let icon = null;
    let filter = null;

    switch (editType) {
      case 'add': { // 添加
        markerLayer = this._addedMarkerLayer;
        icon = {
          type: 'categorical',
          property: 'edit_state',
          stops: [
            ['add', this._markerAddIcon],
            ['add-select', this._markerAddSelIcon],
            ['add-edit', this._markerAddEditIcon],
            ['add-edit-select', this._markerAddSelIcon]
          ],
          default: this._markerAddIcon
        };
        filter = [
          'in',
          'edit_state',
          'add', 'add-select', 'add-edit', 'add-edit-select'
        ];

        // 添加的设施点图层
        if (!this._addedFaciMarkerLayer) {
          this._addedFaciMarkerLayer = new SimpleMarkerLayer({
            map: map,
            minzoom: minZoom,
            icon: {
              type: 'categorical',
              property: 'layer_code',
              stops: [
                ['waterplant', 'wp_sew'],
                ['industryplant', 'wp_ind'],
                ['pumprain', 'ps_rain'],
                ['pumpwaste', 'ps_sew'],
                ['pumpcombine', 'ps_com'],
                ['pumpindustry', 'ps_ind'],
                ['agricwaste', 'rural_sew2'],
                ['manholerain', 'well_rain1x'],
                ['manholewaste', 'well_sew1x'],
                ['manholeindustry', 'well_ind1x'],
                ['interceptionsew', 'faci_intersew'],
                ['interception', 'faci_inter'],
                ['raininlet', 'faci_raininlet'],
                ['storage', 'faci_storage'],
                ['outfall', 'faci_outfall'],
                ['flap', 'faci_outfall'],
                ['gate', 'faci_gate']
              ],
              default: 'marker'
            },
            filter: filter,
            sourceId: 'editor_marker-' + editType,
            layerId: 'editor_marker-' + editType + '-faci'
          });
        }
        break;
      }
      case 'select': { // 选中
        markerLayer = this._selectedMarkerLayer;
        icon = this._markerSelIcon;
        filter = ['==', 'edit_state', editType];
        break;
      }
      case 'edit': { // 编辑
        markerLayer = this._editedMarkerLayer;
        icon = {
          type: 'categorical',
          property: 'edit_state',
          stops: [
            ['edit', this._markerEditIcon],
            ['edit-select', this._markerSelIcon]
          ],
          default: this._markerEditIcon
        };
        filter = ['in', 'edit_state', 'edit', 'edit-select'];
        break;
      }
      case 'delete': { // 删除
        markerLayer = this._deletedMarkerLayer;
        icon = this._markerDelIcon;
        filter = ['==', 'edit_state', editType];
        break;
      }
      default:
        return;
    }

    // 点图层
    if (!markerLayer) {
      markerLayer = new SimpleMarkerLayer({
        map: map,
        minzoom: minZoom,
        icon: icon,
        offset: [0, -20],
        filter: filter,
        sourceId: 'editor_marker-' + editType,
      });

      switch (editType) {
        case 'add': { // 添加
          this._addedMarkerLayer = markerLayer;
          break;
        }
        case 'select': { // 选中
          this._selectedMarkerLayer = markerLayer;
          break;
        }
        case 'edit': { // 编辑
          this._editedMarkerLayer = markerLayer;
          break;
        }
        case 'delete': { // 删除
          this._deletedMarkerLayer = markerLayer;
          break;
        }
        default:
          break;
      }
    }
  }

  /**
   * 初始化线图层
   * @param {String} editType -编辑类型
   */
  _initLineLayer(editType) {
    const map = this._map;
    const minZoom = this._minzoom;

    let lineLayer = null;
    let lineColor = null;
    let lineWidth = this._lineWidth;
    let lineOpacity = 0.75;
    let filter = null;

    switch (editType) {
      case 'add': { // 添加
        lineLayer = this._addedLineLayer;
        lineColor = {
          type: 'categorical',
          property: 'edit_state',
          stops: [
            ['add', this._lineAddColor],
            ['add-select', this._lineSelColor],
            ['add-edit', this._lineSelColor],
            ['add-edit-select', this._lineSelColor],
          ],
          default: this._lineAddColor
        },
        lineOpacity = {
          type: 'categorical',
          property: 'edit_state',
          stops: [
            ['add', 0.01],
            ['add-edit', 0.01]
          ],
          default: 0.75
        },
        filter = [
          'in',
          'edit_state',
          'add', 'add-select', 'add-edit', 'add-edit-select'
        ];

        // 添加的设施线图层
        if (!this._addedFaciLineLayer) {
          this._addedFaciLineLayer = new SimpleLineLayer({
            map: map,
            minzoom: minZoom,
            color: {
              type: 'categorical',
              property: 'layer_code',
              stops: [
                ['pipelinerain', '#13B55C'],
                ['pipelinewaste', '#FF4500'],
                ['pipelineindustry', '#FF00FF'],
                ['ditch', '#138585'],
              ],
              default: '#FF4500'
            },
            width: this._lineWidth,
            opacity: 0.75,
            filter: filter,
            sourceId: 'editor_line-' + editType,
            layerId: 'editor_line-' + editType + '-faci'
          });
        }
        break;
      }
      case 'select': { // 选中
        lineLayer = this._selectedLineLayer;
        lineColor = this._lineSelColor;
        filter = ['==', 'edit_state', editType];
        break;
      }
      case 'edit': { // 编辑
        lineLayer = this._editedLineLayer;
        lineColor = this._lineSelColor;
        filter = ['in', 'edit_state', 'edit', 'edit-select', 'edit-reverse', 'edit-reverse-select'];
        break;
      }
      case 'delete': { // 删除
        lineLayer = this._deletedLineLayer;
        lineColor = this._lineDelColor;
        lineWidth = 11.5;
        lineOpacity = 0.95;
        filter = ['==', 'edit_state', editType];
        break;
      }
      default:
        return;
    }

    // 线图层
    if (!lineLayer) {
      lineLayer = new SimpleLineLayer({
        map: map,
        minzoom: minZoom,
        color: lineColor,
        width: lineWidth,
        opacity: lineOpacity,
        filter: filter,
        sourceId: 'editor_line-' + editType
      });

      switch (editType) {
        case 'add': { // 添加
          this._addedLineLayer = lineLayer;
          break;
        }
        case 'select': { // 选中
          this._selectedLineLayer = lineLayer;
          break;
        }
        case 'edit': { // 编辑
          this._editedLineLayer = lineLayer;
          break;
        }
        case 'delete': { // 删除
          this._deletedLineLayer = lineLayer;
          break;
        }
        default:
          break;
      }
    }

    // 线中心点图层
    if (!this._lineCenterMarkerLayer) {
      this._lineCenterMarkerLayer = new SimpleMarkerLayer({
        map: map,
        minzoom: minZoom,
        icon: {
          type: 'categorical',
          property: 'edit_state',
          stops: [
            ['add', this._markerAddIcon],
            ['add-select', this._markerAddSelIcon],
            ['add-edit', this._markerAddEditIcon],
            ['add-edit-select', this._markerAddSelIcon],
            ['edit', this._markerEditIcon],
            ['edit-select', this._markerSelIcon],
            ['edit-reverse', this._markerEditIcon],
            ['edit-reverse-select', this._markerSelIcon],
            ['delete', this._markerDelIcon]
          ],
          default: this._markerSelIcon
        },
        offset: [0, -15],
        filter: [
          'in',
          'edit_state',
          'add', 'add-select', 'add-edit', 'add-edit-select', 'edit', 'edit-select', 'edit-reverse', 'edit-reverse-select', 'delete'
        ],
        sourceId: 'editor_line_center',
      });
    }

    // 线流向点图层
    if (!this._lineDirectionMarkerLayer) {
      this._lineDirectionMarkerLayer = new SimpleMarkerLayer({
        map: map,
        minzoom: minZoom,
        icon: this._arrowIcon,
        filter: [
          'in',
          'edit_state',
          'edit-reverse', 'edit-reverse-select'
        ],
        sourceId: 'editor_line_direction',
      });
      // 设置图标旋转的角度
      this._lineDirectionMarkerLayer.setLayoutProperty('icon-rotate', ['get', 'bearing']);
    }
  }

  /**
   * 更新数据
   * @param {Array} data -GeoJSON要素集合
   */
  _updateData(data) {
    // 点数据
    this._pointFC.features = data.filter((fea) => {
      return fea.geometry.type.toLowerCase() === 'point';
    });
    // 更新编辑状态
    this._pointFC.features.forEach((fea) => {
      if (fea.properties.edit_state.indexOf('add') === 0) {
        fea.properties.edit_state = 'add';
      } else if (fea.properties.edit_state.indexOf('edit') === 0) {
        fea.properties.edit_state = 'edit';
      }
    });
    const pointFC = this._pointFC;

    // 线数据
    this._polylineFC.features = data.filter((fea) => {
      return fea.geometry.type.toLowerCase() === 'linestring' ||
             fea.geometry.type.toLowerCase() === 'multilinestring';
    });
    // 更新编辑状态
    this._polylineFC.features.forEach((fea) => {
      if (fea.properties.edit_state.indexOf('add') === 0) {
        fea.properties.edit_state = 'add';
      } else if (fea.properties.edit_state.indexOf('edit') === 0) {
        fea.properties.edit_state = 'edit';
      }
    });
    this._centerPointFC.features = [];

    const lineFC = this._polylineFC;
    const centerFC = this._centerPointFC;

    // 更新点数据
    this._addedFaciMarkerLayer.setData(pointFC);
    this._addedMarkerLayer.setData(pointFC);
    this._selectedMarkerLayer.setData(pointFC);
    this._editedMarkerLayer.setData(pointFC);
    this._deletedMarkerLayer.setData(pointFC);

    // 更新线数据
    this._addedLineLayer.setData(lineFC);
    this._addedFaciLineLayer.setData(lineFC);
    this._selectedLineLayer.setData(lineFC);
    this._editedLineLayer.setData(lineFC);
    this._deletedLineLayer.setData(lineFC);

    centerFC.features = lineFC.features.map((fea) => {
      // 获取线中点要素
      const coordinates = GeogUtils.calcCenter(fea);

      // 计算线的方位角
      if (fea.properties.edit_state === 'edit') {
        let coordsLen = fea.geometry.coordinates.length;
        let startLonLat = fea.geometry.coordinates[0];
        let endLonLat = fea.geometry.coordinates[coordsLen - 1];

        // 计算方位角
        fea.properties.bearing = GeogUtils.bearing(startLonLat, endLonLat);
        // 更新编辑状态
        fea.properties.edit_state = 'edit-reverse';
      }
      return GeoJsonProvider.getPointFeature(coordinates, fea.properties);
    });
    // 更新线中点数据
    this._lineCenterMarkerLayer.setData(centerFC);
    this._lineDirectionMarkerLayer.setData(centerFC);
  }

  /**
   * 更新点数据
   * @param {String} editType -编辑类型
   * @param {Array} data -GeoJSON要素集合
   */
  _updateMarkerData(editType, data) {
    const fc = this._pointFC;

    switch (editType) {
      case 'add': { // 添加
        // 更新编辑状态
        data.forEach((fea) => {
          fea.properties.edit_state = editType;
        });
        // 合并数据
        fc.features = fc.features.concat(data);

        // 更新数据源
        this._addedFaciMarkerLayer.setData(fc);
        this._addedMarkerLayer.setData(fc);
        break;
      }
      case 'select': { // 选中
        let isSelAdd = false;  // 是否选中添加的要素
        let isSelEdit = false; // 是否选中编辑的要素

        // 去掉添加、编辑的选中状态
        fc.features.forEach((feature) => {
          switch (feature.properties.edit_state) {
            case 'add-select': {
              feature.properties.edit_state = 'add';
              isSelAdd = true;
              break;
            }
            case 'add-edit-select': {
              feature.properties.edit_state = 'add-edit';
              isSelAdd = true;
              break;
            }
            case 'edit-select': {
              feature.properties.edit_state = 'edit';
              isSelEdit = true;
              break;
            }
            default:
              break;
          }
        });

        for (let i = 0; i < data.length; i++) {
          const item = data[i];
          item.properties.edit_state = item.properties.edit_state || 'select';

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length > 0) {
            // 要素存在, 更新添加、删除的选中
            existFeas.forEach((fea) => {
              switch (fea.properties.edit_state) {
                case 'add': {
                  fea.properties.edit_state = 'add-select';
                  isSelAdd = true;
                  break;
                }
                case 'add-edit': {
                  fea.properties.edit_state = 'add-edit-select';
                  isSelAdd = true;
                  break;
                }
                case 'edit': {
                  fea.properties.edit_state = 'edit-select';
                  isSelEdit = true;
                  break;
                }
              }
            });
          } else {
            // 要素不存在, 添加/更新选中要素
            let selectedFeas = fc.features.filter((feature) => {
              // heyukun mod 2023-5-30
              //return feature.properties.edit_state === 'select'
              return (
                feature.properties.edit_state === 'select' &&
                feature.properties.fid === item.properties.fid
              )
            });
            if (selectedFeas.length === 0) {
              fc.features.push(item);
            } else {
              selectedFeas[0].geometry = item.geometry;
              selectedFeas[0].properties = item.properties;
            }
          }
        } // end of for (...)

        // 更新数据源
        this._selectedMarkerLayer.setData(fc);
        if (isSelAdd) {
          this._addedMarkerLayer.setData(fc);
        }
        if (isSelEdit) {
          this._editedMarkerLayer.setData(fc);
        }
        break;
      }
      case 'edit': { // 编辑
        let isEditAdd = false; // 是否编辑添加的要素

        for (let i = 0; i < data.length; i++) {
          const item = data[i];

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length === 0) continue;

          existFeas.forEach((fea) => {
            // 更新状态
            let editState = fea.properties.edit_state;

            fea.properties = item.properties;
            fea.properties.hasProperty = true;

            switch (editState) {
              case 'add':
              case 'add-select':
              case 'add-edit-select': {
                fea.properties.edit_state = 'add-edit';
                isEditAdd = true;
                break;
              }
              case 'select':
              case 'edit-select': {
                fea.properties.edit_state = 'edit';
                break;
              }
              default:
                break;
            }
          });
        }

        // 更新数据源
        this._editedMarkerLayer.setData(fc);
        this._selectedMarkerLayer.setData(fc);
        if (isEditAdd) {
          this._addedMarkerLayer.setData(fc);
        }
        break;
      }
      case 'delete': { // 删除
        let isDelAdd = false;  // 是否删除添加的要素
        let isDelSel = false;  // 是否删除选中的要素
        let isDelEdit = false; // 是否删除编辑的要素

        for (let i = 0; i < data.length; i++) {
          const item = data[i];

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length === 0) continue;

          existFeas.forEach((fea) => {
            let editState = fea.properties.edit_state;
            isDelAdd = editState.indexOf('add') === 0;
            isDelEdit = editState.indexOf('edit') === 0;

            if (editState === 'select') {
              fea.properties.edit_state = 'delete';
              isDelSel = true;
            } else if (isDelEdit) {
              fea.properties.edit_state = 'delete';
            }

          });
        }

        if (isDelAdd) {
          // 过滤非添加的数据
          fc.features = fc.features.filter((fea) => {
            const found = data.find((item) => item.properties.fid === fea.properties.fid);
            return (
              !found ||
              (found && fea.properties.edit_state.indexOf('add') < 0)
            );
          });
        }

        // 更新数据源
        this._deletedMarkerLayer.setData(fc);
        if (isDelSel) {
          this._selectedMarkerLayer.setData(fc);
        }
        if (isDelEdit) {
          this._editedMarkerLayer.setData(fc);
        }
        if (isDelAdd) {
          this._addedMarkerLayer.setData(fc);
          this._addedFaciMarkerLayer.setData(fc);
        }
        break;
      }
      default:
        return;
    }
  }

  /**
   * 更新线数据
   * @param {String} editType -编辑类型
   * @param {Array} data -GeoJSON要素集合
   */
  _updateLineData(editType, data) {
    const fc = this._polylineFC;
    const centerFC = this._centerPointFC;

    switch (editType) {
      case 'add': { // 添加
        // 更新编辑状态
        data.forEach((fea) => {
          fea.properties.edit_state = editType;

          const coordinates = GeogUtils.calcCenter(fea);
          let centerFea = GeoJsonProvider.getPointFeature(coordinates, fea.properties);
          centerFC.features.push(centerFea);
        });
        // 合并数据
        fc.features = fc.features.concat(data);

        // 更新数据源
        this._addedLineLayer.setData(fc);
        this._addedFaciLineLayer.setData(fc);
        this._lineCenterMarkerLayer.setData(centerFC);

        // 移动线图层
        this._moveLineLayer('add');
        break;
      }
      case 'select': { // 选中
        let isSelAdd = false;  // 是否选中添加的要素
        let isSelEdit = false; // 是否选中编辑的要素

        // 去掉添加、编辑的选中状态
        fc.features.forEach((feature) => {
          switch (feature.properties.edit_state) {
            case 'add-select': {
              feature.properties.edit_state = 'add';
              isSelAdd = true;
              break;
            }
            case 'add-edit-select': {
              feature.properties.edit_state = 'add-edit';
              isSelAdd = true;
              break;
            }
            case 'edit-select': {
              feature.properties.edit_state = 'edit';
              isSelEdit = true;
              break;
            }
            case 'edit-reverse-select': {
              feature.properties.edit_state = 'edit-reverse';
              isSelEdit = true;
              break;
            }
            default:
              break;
          }
        });

        for (let i = 0; i < data.length; i++) {
          const item = data[i];
          item.properties.edit_state = item.properties.edit_state || 'select';

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length > 0) {
            // 要素存在, 更新添加、编辑的选中
            existFeas.forEach((fea) => {
              switch (fea.properties.edit_state) {
                case 'add': {
                  fea.properties.edit_state = 'add-select';
                  isSelAdd = true;
                  break;
                }
                case 'add-edit': {
                  fea.properties.edit_state = 'add-edit-select';
                  isSelAdd = true;
                  break;
                }
                case 'edit': {
                  fea.properties.edit_state = 'edit-select';
                  isSelEdit = true;
                  break;
                }
                case 'edit-reverse': {
                  fea.properties.edit_state = 'edit-reverse-select';
                  isSelEdit = true;
                  break;
                }
                default:
                  break;
              }
            });
          } else {
            // 要素不存在, 添加/更新选中要素
            let selectedFeas = fc.features.filter((feature) => {
              // heyukun mod 2023-5-30
              //return feature.properties.edit_state === 'select';
              return (
                feature.properties.edit_state === 'select' &&
                feature.properties.fid === item.properties.fid
              )
            });
            if (selectedFeas.length === 0) {
              fc.features.push(item);
            } else {
              selectedFeas[0].geometry = item.geometry;
              selectedFeas[0].properties = item.properties;
            }
          }
        } // end of for (...)

        // 更新数据源
        this._selectedLineLayer.setData(fc);
        if (isSelAdd) {
          this._addedLineLayer.setData(fc);
          // 移动线图层
          this._moveLineLayer('add');
        }
        if (isSelEdit) {
          this._editedLineLayer.setData(fc);
          // 移动线图层
          this._moveLineLayer('edit');
        }
        if (isSelAdd || isSelEdit) {
          this._lineCenterMarkerLayer.setData(centerFC);
        }
        break;
      }
      case 'edit': { // 编辑
        let isEditAdd = false;  // 是否编辑添加的要素
        let isEditSel = false;  // 是否编辑选中的要素
        let isEditEdit = false; // 是否编辑编辑的要素

        for (let i = 0; i < data.length; i++) {
          const item = data[i];

          // 更新线要素属性
          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length === 0) continue;

          existFeas.forEach((fea) => {
            // 更新状态
            let editState = fea.properties.edit_state;

            fea.properties = item.properties;
            fea.properties.hasProperty = true;

            if (editState === 'select') {
              fea.properties.edit_state = 'edit';
              isEditSel = true;

              // 添加线中点要素
              const coordinates = GeogUtils.calcCenter(fea);
              const centerFea = GeoJsonProvider.getPointFeature(coordinates, fea.properties);
              centerFC.features.push(centerFea);
            } else {
              switch (editState) {
                case 'add':
                case 'add-select':
                case 'add-edit-select': {
                  fea.properties.edit_state = 'add-edit';
                  isEditAdd = true;
                  break;
                }
                case 'edit-select': {
                  fea.properties.edit_state = 'edit';
                  isEditEdit = true;
                  break;
                }
                case 'edit-reverse-select': {
                  fea.properties.edit_state = 'edit-reverse';
                  isEditEdit = true;
                }
                default:
                  break;
              }
              if (isEditAdd || isEditEdit) {
                // 更新线中点要素属性
                let existCenterFeas = centerFC.features.filter((centerFea) => {
                  return centerFea.properties.fid === fea.properties.fid;
                });
                if (existCenterFeas.length > 0) {
                  existCenterFeas[0].properties = fea.properties;
                }
              }
            }
          });
        } // end of for (...)

        // 更新数据源
        this._editedLineLayer.setData(fc);
        if (isEditSel) {
          this._selectedLineLayer.setData(fc);
          // 移动线图层
          this._moveLineLayer('edit');
        }
        if (isEditAdd || isEditEdit || isEditSel) {
          this._lineCenterMarkerLayer.setData(centerFC);
        }
        break;
      }
      case 'reverse': { // 编辑-反转
        for (let i = 0; i < data.length; i++) {
          const item = data[i];

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length === 0) continue;

          existFeas.forEach((fea) => {
            let editState = fea.properties.edit_state;
            if (editState !== 'edit-reverse-select' &&
                editState.indexOf('select') >= 0) { // 选中/编辑选中
              // 反转图形
              GeogUtils.reverse(fea);

              let coordsLen = fea.geometry.coordinates.length;
              let startLonLat = fea.geometry.coordinates[0];
              let endLonLat = fea.geometry.coordinates[coordsLen - 1];

              // 更新属性
              let inNodeId = fea.properties.in_nodeid;
              fea.properties.in_nodeid = fea.properties.out_nodeid;
              fea.properties.out_nodeid = inNodeId;
              // 计算方位角
              fea.properties.bearing = GeogUtils.bearing(startLonLat, endLonLat);
              // 更新编辑状态
              fea.properties.edit_state = 'edit-reverse';

              // 添加线中点要素
              const coordinates = GeogUtils.calcCenter(fea);
              const centerFea = GeoJsonProvider.getPointFeature(coordinates, fea.properties);
              centerFC.features.push(centerFea);
            }
          });
        } // end of for (...)

        // 更新数据源
        this._editedLineLayer.setData(fc);
        this._lineCenterMarkerLayer.setData(centerFC);
        this._lineDirectionMarkerLayer.setData(centerFC);

        // 移动线图层
        this._moveLineLayer('edit');
        break;
      }
      case 'delete': { // 删除
        let isDelAdd = false;  // 是否删除添加的要素
        let isDelSel = false;  // 是否删除选中的要素
        let isDelEdit = false; // 是否删除编辑的要素

        for (let i = 0; i < data.length; i++) {
          const item = data[i];

          const existFeas = fc.features.filter((fea) => {
            return fea.properties.fid === item.properties.fid;
          });
          if (existFeas.length === 0) continue;

          existFeas.forEach((fea) => {
            let editState = fea.properties.edit_state;
            isDelAdd = editState.indexOf('add') === 0;
            isDelEdit = editState.indexOf('edit') === 0;

            if (editState === 'select') {
              fea.properties.edit_state = 'delete';
              isDelSel = true;

              // 添加线中点
              const coordinates = GeogUtils.calcCenter(fea);
              const centerFea = GeoJsonProvider.getPointFeature(coordinates, fea.properties);
              centerFC.features.push(centerFea);
            } else if (isDelEdit) {
              fea.properties.edit_state = 'delete';
            }
          });
        } // end of for (...)

        if (isDelAdd) {
          // 过滤非添加的数据
          fc.features = fc.features.filter((fea) => {
            const found = data.find((item) => item.properties.fid === fea.properties.fid);
            return (
              !found ||
              (found && fea.properties.edit_state.indexOf('add') < 0)
            );
          });
          // 过滤非添加的线中点数据
          centerFC.features = centerFC.features.filter((fea) => {
            const found = data.find((item) => item.properties.fid === fea.properties.fid);
            return (
              !found ||
              (found && fea.properties.edit_state.indexOf('add') < 0)
            );
          });
        }

        // 更新数据源
        this._deletedLineLayer.setData(fc);
        // 移动线图层
        this._moveLineLayer('delete');

        if (isDelEdit) {
          this._editedLineLayer.setData(fc);
          // 移动线图层
          this._moveLineLayer('edit');
        }
        if (isDelSel) {
          this._selectedLineLayer.setData(fc);
        }
        if (isDelAdd) {
          this._addedLineLayer.setData(fc);
          this._addedFaciLineLayer.setData(fc);
          // 移动线图层
          this._moveLineLayer('add');
        }
        if (isDelAdd || isDelEdit || isDelSel) {
          this._lineCenterMarkerLayer.setData(centerFC);
        }
        break;
      }
      default:
        return;
    }
  }

  /**
   * 缩放到要素范围
   */
  _fitBounds() {
    const map = this._map;
    const pointFC = this._pointFC;
    const lineFC = this._polylineFC;

    // 计算包围盒
    let bboxP = [], bboxL = [];
    if (pointFC.features.length > 0) {
      let pntFea = pointFC.features[0]
      bboxP = pointFC.features.length === 1
              ? [pntFea.geometry.coordinates, pntFea.geometry.coordinates]
              : GeogUtils.calcBBox(pointFC);
    }
    if (lineFC.features.length > 0) {
      bboxL = GeogUtils.calcBBox(lineFC);
    }

    // 缩放至要素范围
    const zoom = 15.75;
    if (bboxP.length > 0 || bboxL.length > 0) {
      let bbox = [];
      let isJumpTo = false;
      if (bboxP.length === 1 && bboxL.length === 0) {
        isJumpTo = true;
      } else if (bboxP.length > 0 && bboxL.length === 0) {
        bbox = bboxP;
      } else if (bboxP.length === 0 && bboxL.length > 0) {
        bbox = bboxL;
      } else {
        bbox = [
          [Math.min(bboxP[0][0], bboxL[0][0]), Math.min(bboxP[0][1], bboxL[0][1])],
          [Math.max(bboxP[1][0], bboxL[1][0]), Math.max(bboxP[1][1], bboxL[1][1])]
        ];
      }

      if (isJumpTo) {
        MapProvider.jumpTo(map, bboxP[0], zoom);
      } else {
        MapProvider.fitBounds(map, bbox, zoom, true);
      }
    }
  }

  /**
   * 添加日志
   * @param {String} editType -编辑类型
   * @param {Array} data -GeoJSON要素集合
   */
  _appendLog(editType, data) {
    /*
    let log = this._editingLog;
    let newIndex = log.length;

    let logItems = data.map((fea) => {
      const props = fea.properties;

      let newEditState = null;
      if (editType !== 'delete' && log.length > 0) {
        let prevFea = null;
        for (let i = log.length - 1; i >= 0; i--) {
          if (log[i].feature.properties.fid === props.fid) {
            prevFea = log[i].feature;
            break;
          }
        }
        if (prevFea && prevFea.properties.edit_state.indexOf('add') === 0) {
          newEditState = 'add-edit';
        }
      }

      // 克隆要素
      let currFea = GeoJsonProvider.cloneFeature(fea);
      if (editType === 'reverse') {
        currFea.properties.edit_state = 'edit-reverse';
      } else {
        currFea.properties.edit_state = newEditState || editType;
      }

      let logItem = {
        index: newIndex,
        edit_state: editType === 'reverse' ? 'edit' : editType,
        fid: props.fid,
        layer_code: props.layer_code,
        type: getType(fea.geometry.type), // 类型
        enable: true, // 可操作
        feature: currFea
      };

      return logItem;
    });
    // 合并日志项
    this._editingLog = log.concat(logItems);
    */

    // new
    let editLog = this._editLog;
    let startIndex = editLog.length;
    let geomType = null;

    let itemFeatures = data.map((item) => {
      const props = item.properties;
      if (!geomType) {
        geomType = getType(item.geometry.type);
      }

      let newEditState = null;
      if (editType !== 'delete' && editLog.length > 0) {
        let prevFea = null;
        for (let i = editLog.length - 1; i >= 0; i--) {
          const prevFeas = editLog[i].features.filter((fea) => {
            return fea.properties.fid === props.fid
          });
          if (prevFeas.length > 0) {
            prevFea = prevFeas[i];
            break;
          }
        }
        if (prevFea && prevFea.properties.edit_state.indexOf('add') === 0) {
          newEditState = 'add-edit';
        }
      }

      // 克隆要素
      let currFea = GeoJsonProvider.cloneFeature(item);
      if (editType === 'reverse') {
        currFea.properties.edit_state = 'edit-reverse';
      } else {
        currFea.properties.edit_state = newEditState || editType;
      }

      return currFea;
    });

    // 添加日志项
    this._editLog.push({
      index: startIndex,
      edit_state: editType === 'reverse' ? 'edit' : editType,
      type: geomType,
      features: itemFeatures
    });

    /**
     * 获取图层类型
     * @param {String} geomType -几何图形类型
     *
     * @returns {String}
     */
    function getType(geomType) {
      switch (geomType.toLowerCase()) {
        case 'point':
        case 'multipoint': { // 点/多点
          return 'marker';
        }
        case 'linestring':
        case 'multilinestring': { // 折线/多折线
          return 'line';
        }
        case 'polygon':
        case 'multipolygon': { // 多边形/多多边形
          return 'fill';
        }
        default:
          return null;
      }
    }
  }

  /**
   * 清除选中的点数据
   */
  _clearSelectedMarkerData() {
    const fc = this._pointFC;

    let isSel = false;     // 是否有选中的要素
    let isSelAdd = false;  // 是否选中添加的要素
    let isSelEdit = false; // 是否选中编辑的要素

    fc.features.forEach((fea) => {
      isSel = fea.properties.edit_state === 'select';

      switch (fea.properties.edit_state) {
        case 'add-select': {
          fea.properties.edit_state = 'add';
          isSelAdd = true;
          break;
        }
        case 'add-edit-select': {
          fea.properties.edit_state = 'add-edit';
          isSelAdd = true;
          break;
        }
        case 'edit-select': {
          fea.properties.edit_state = 'edit';
          isSelEdit = true;
          break;
        }
        default:
          break;
      }
    });
    // 除去选中的要素
    fc.features = fc.features.filter((fea) => {
      return fea.properties.edit_state !== 'select';
    });

    // 更新数据源
    if (isSel) {
      this._selectedMarkerLayer.setData(fc);
    }
    if (isSelAdd) {
      this._addedMarkerLayer.setData(fc);
    }
    if (isSelEdit) {
      this._editedMarkerLayer.setData(fc);
    }
  }

  /**
   * 清除选中的线数据
   */
  _clearSelectedLineData() {
    const fc = this._polylineFC;
    const centerFC = this._centerPointFC;

    let isSel = false;     // 是否有选中的要素
    let isSelAdd = false;  // 是否选中添加的要素
    let isSelEdit = false; // 是否选中编辑的要素

    fc.features.forEach((fea) => {
      isSel = fea.properties.edit_state === 'select';

      switch (fea.properties.edit_state) {
        case 'add-select': {
          fea.properties.edit_state = 'add';
          isSelAdd = true;
          break;
        }
        case 'add-edit-select': {
          fea.properties.edit_state = 'add-edit';
          isSelAdd = true;
          break;
        }
        case 'edit-select': {
          fea.properties.edit_state = 'edit';
          isSelEdit = true;
          break;
        }
        case 'edit-reverse-select': {
          fea.properties.edit_state = 'edit-reverse';
          isSelEdit = true;
          break;
        }
        default:
          break;
      }
    });
    // 除去选中的要素
    fc.features = fc.features.filter((fea) => {
      return fea.properties.edit_state !== 'select';
    });

    // 更新数据源
    if (isSel) {
      this._selectedLineLayer.setData(fc);
    }
    if (isSelAdd) {
      this._addedLineLayer.setData(fc);
    }
    if (isSelEdit) {
      this._editedLineLayer.setData(fc);
    }
    if (isSelAdd || isSelEdit) {
      this._lineCenterMarkerLayer.setData(centerFC);
    }
  }

  /**
   * 移动线图层到中点图层下面
   * @param {String} editType -编辑类型
   */
  _moveLineLayer(editType) {
    const map = this._map;
    const centerLayerId = this._lineCenterMarkerLayer._layerId;
    const directionLayerId = this._lineDirectionMarkerLayer._layerId

    switch (editType) {
      case 'add': { // 添加
        if (!this._isAddedLineLayerMoved) {
          if (LayerProvider.hasLayer(map, centerLayerId)) {
            LayerProvider.moveLayer(map, this._addedLineLayer._layerId, centerLayerId);
          }
          this._isAddedLineLayerMoved = true;
        }
        break;
      }
      case 'edit': { // 编辑
        if (!this._isEditedLineLayerMoved) {
          if (LayerProvider.hasLayer(map, centerLayerId)) {
            LayerProvider.moveLayer(map, this._editedLineLayer._layerId, centerLayerId);
          }
          if (LayerProvider.hasLayer(map, directionLayerId)) {
            LayerProvider.moveLayer(map, this._editedLineLayer._layerId, directionLayerId);
          }
          this._isEditedLineLayerMoved = true;
        }
        break;
      }
      case 'delete': { // 删除
        if (!this._isDeletedLineLayerMoved) {
          if (LayerProvider.hasLayer(map, centerLayerId)) {
            LayerProvider.moveLayer(map, this._deletedLineLayer._layerId, centerLayerId);
          }
          if (LayerProvider.hasLayer(map, directionLayerId)) {
            LayerProvider.moveLayer(map, this._deletedLineLayer._layerId, directionLayerId);
          }
          this._isDeletedLineLayerMoved = true;
        }
        break;
      }
      default:
        break;
    }
  }
}
