import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
import _createClass from 'babel-runtime/helpers/createClass';
import _inherits from 'babel-runtime/helpers/inherits';
/**
 * @文件说明: 定义矢量Layers图层的基类
 * @创建人: pjtools@vip.qq.com
 * @创建时间: 2020-05-22 15:14:20
 */

import BasicMapApi from '../../util/basicMapApiClass';
import hat from 'hat';
import cloneDeep from 'lodash/cloneDeep';
import round from 'lodash/round';
import omitBy from 'lodash/omitBy';
import remove from 'lodash/remove';
import find from 'lodash/find';
import filter from 'lodash/filter';
import assign from 'lodash/assign';
import { isEmpty, isNumeric, isNotEmptyArray, isArray, isString, isBooleanTrue } from '../../../_util/methods-util';

// 矢量图层的原生MapboxGL默认参数
export var defaultVectorLayerOptions = {
  layout: {
    visibility: 'visible'
  },
  metadata: {
    layerType: 'VectorLayer'
  }
};

// 矢量图层的基础扩展参数
export var defaultVectorBasicOptions = {
  // 是否添加指定图层前
  beforeId: null,
  // 是否添加到图层组中
  layerGroupId: null,
  // 图层透明度
  opacity: 1
};

var _id = Symbol('id');
var _opacity = Symbol('opacity');
var _turf = Symbol('turf');
var _initLayerOptions = Symbol('initLayerOptions');
var _options = Symbol('options');
var _mapLayer = Symbol('mapLayer');
var _mapLayerGroup = Symbol('mapLayerGroup');

var BasicLayerClass = function (_BasicMapApi) {
  _inherits(BasicLayerClass, _BasicMapApi);

  _createClass(BasicLayerClass, [{
    key: 'id',
    get: function get() {
      return this[_id];
    }
  }, {
    key: 'turf',
    get: function get() {
      return this[_turf];
    }

    // 初始原生图层参数

  }, {
    key: 'initLayerOptions',
    get: function get() {
      return this[_initLayerOptions];
    }

    // 图层参数选项

  }, {
    key: 'options',
    get: function get() {
      return this[_options];
    }

    // 图层到地图中的实例对象

  }, {
    key: 'mapLayer',
    get: function get() {
      return this[_mapLayer] || null;
    }

    // 图层组到地图中的对象

  }, {
    key: 'mapLayerGroup',
    get: function get() {
      return this[_mapLayerGroup] || null;
    }

    // 图层整体透明度

  }, {
    key: 'opacity',
    get: function get() {
      return this[_opacity];
    }
  }]);

  function BasicLayerClass(iMapApi, id, layerOptions, options) {
    _classCallCheck(this, BasicLayerClass);

    var _this = _possibleConstructorReturn(this, (BasicLayerClass.__proto__ || Object.getPrototypeOf(BasicLayerClass)).call(this, iMapApi));

    _this[_turf] = iMapApi && iMapApi.exports && iMapApi.exports.turf;
    _this[_id] = id || hat();
    // 仅保留专属类型的Paint和Layout属性
    var copyLayerOptions = cloneDeep(layerOptions);
    var regexp = new RegExp('^' + (copyLayerOptions.type === 'symbol' ? '(' + copyLayerOptions.type + '|icon|text)' : copyLayerOptions.type) + '-.*?');
    copyLayerOptions.paint = omitBy(copyLayerOptions.paint, function (value, key) {
      return !regexp.test(key);
    });
    copyLayerOptions.layout = omitBy(copyLayerOptions.layout, function (value, key) {
      return !regexp.test(key);
    });
    copyLayerOptions.layout['visibility'] = layerOptions.layout['visibility'];
    // 记录初始图层属性
    copyLayerOptions.id = _this[_id];
    _this[_initLayerOptions] = cloneDeep(copyLayerOptions);

    // 设定图层的Paint属性透明度
    if (options.opacityPaints && !isEmpty(options.opacity)) {
      options.opacity = getCheckOpacity(options.opacity);
      copyLayerOptions.paint = setLayerPaintOpacity(_this[_initLayerOptions].paint, options.opacityPaints, options.opacity);
    }
    _this[_opacity] = options.opacity;
    _this[_options] = options;

    // 设置图层数据源
    if (copyLayerOptions && copyLayerOptions.type !== 'background') {
      var features = options.data ? getSourceFeatures(options.data) : [];
      // 获取字符串型数据源的数据集合
      if (copyLayerOptions.source && isString(copyLayerOptions.source)) {
        var source = iMapApi.getSource(copyLayerOptions.source);
        // 如果存在数据源则直接追加数据集合
        if (source) {
          var sourceFeatures = getSourceFeatures(source._data);
          sourceFeatures.push.apply(sourceFeatures, _toConsumableArray(features));
          source.setData(_this.turf.featureCollection(sourceFeatures));
        } else {
          copyLayerOptions.source = { type: 'geojson', data: _this.turf.featureCollection(features) };
        }
      } else {
        var sourceData = copyLayerOptions.source && copyLayerOptions.source.data;
        features.push.apply(features, _toConsumableArray(getSourceFeatures(sourceData)));
        // 追加数据源
        copyLayerOptions.source = { type: 'geojson', data: _this.turf.featureCollection(features) };
      }
    }

    // 添加图层到地图Map中
    if (iMapApi) {
      // 判断是否添加图层组
      if (_this[_options].layerGroupId) {
        var checkLayer = iMapApi.getLayer(_this[_id], _this[_options].layerGroupId);
        if (checkLayer) {
          _this[_mapLayerGroup] = iMapApi.getLayer(_this[_options].layerGroupId);
          _this[_mapLayer] = checkLayer;
          console.error('\u56FE\u5C42\u7EC4[' + _this[_options].layerGroupId + ']\u4E2D\u56FE\u5C42[' + _this[_id] + ']\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u6DFB\u52A0\u56FE\u5C42.');
        } else {
          _this[_mapLayerGroup] = iMapApi.addLayerToGroup(_this[_options].layerGroupId, copyLayerOptions, _this[_options].beforeId);
          _this[_mapLayer] = iMapApi.getLayer(_this[_id], _this[_options].layerGroupId);
        }
      } else {
        var _checkLayer = iMapApi.getLayer(_this[_id]);
        if (_checkLayer) {
          _this[_mapLayer] = _checkLayer;
          console.error('\u56FE\u5C42[' + _this[_id] + ']\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u91CD\u590D\u6DFB\u52A0\u56FE\u5C42.');
        } else {
          _this[_mapLayer] = iMapApi.addLayer(copyLayerOptions, _this[_options].beforeId);
        }
      }
    }
    return _this;
  }

  // 设置图层的整体透明度
  // 注意：
  // 1、透明度是根据初始图层样式进行相乘计算而来；
  // 2、如属性值为表达式则忽略


  _createClass(BasicLayerClass, [{
    key: 'setOpacity',
    value: function setOpacity(opacity) {
      var _this2 = this;

      var paints = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

      if (this[_opacity] !== opacity) {
        this[_opacity] = getCheckOpacity(opacity);
      }
      var copyPaint = cloneDeep(this.initLayerOptions.paint);
      paints && paints.map(function (key) {
        if (isNumeric(_this2.getPaint(key)) && isNumeric(copyPaint[key])) {
          _this2.setPaint(key, round(copyPaint[key] * _this2.opacity, 2));
        }
      });
    }

    /**
     * 移除当前图层
     */

  }, {
    key: 'remove',
    value: function remove() {
      // 判断是否添加图层组
      if (this[_options].layerGroupId) {
        this.iMapApi.removeLayerToGroup(this[_options].layerGroupId, this[_id]);
      } else {
        this.iMapApi.removeLayer(this[_id]);
      }
      // 清空图层属性
      this[_mapLayer] = null;
      this[_mapLayerGroup] = null;
    }

    /**
     * 获取指定名称的Paint属性
     * @param {String} key 待获取的Paint属性名
     */

  }, {
    key: 'getPaint',
    value: function getPaint(key) {
      var map = this.iMapApi.map;
      return map.getPaintProperty(this.id, key);
    }

    /**
     * 设置指定名称的Paint属性
     * @param {String} key 图层的Paint属性名
     * @param {Any} value 图层Paint属性的值
     * @param {Object} options 设置图层Paint属性的参数选项
     */

  }, {
    key: 'setPaint',
    value: function setPaint(key, value) {
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

      var map = this.iMapApi.map;
      map.setPaintProperty(this.id, key, value, options);
    }

    /**
     * 获取指定名称的Layout属性
     * @param {String} key 待获取的Layout属性名
     */

  }, {
    key: 'getLayout',
    value: function getLayout(key) {
      var map = this.iMapApi.map;
      return map.getLayoutProperty(this.id, key);
    }

    /**
     * 设置指定名称的Layout属性
     * @param {String} key 图层的Layout属性名
     * @param {Any} value 图层Layout属性的值
     * @param {Object} options 设置图层Layout属性的参数选项
     */

  }, {
    key: 'setLayout',
    value: function setLayout(key, value) {
      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

      var map = this.iMapApi.map;
      map.setLayoutProperty(this.id, key, value, options);
    }

    /**
     * 获取图层的数据过滤器
     */

  }, {
    key: 'getFilter',
    value: function getFilter() {
      var map = this.iMapApi.map;
      return map.getFilter(this.id);
    }

    /**
     * 设置图层的数据过滤条件
     * @param {Array} filter 图层数据过滤条件
     * @param {Object} options 设置图层数据过滤器的参数选项
     */

  }, {
    key: 'setFilter',
    value: function setFilter() {
      var filter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      var map = this.iMapApi.map;
      map.setFilter(this.id, filter, options);
    }

    /**
     * 设置图层的最小与最大层级区间渲染范围
     * @param {Number} minzoom 图层最小层级
     * @param {Number} maxzoom 图层最大层级
     * @param {Boolean} isLayerGroup 是否图层组统一设置
     */

  }, {
    key: 'setZoomRange',
    value: function setZoomRange(minzoom, maxzoom) {
      var isLayerGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      // 判断是否整个图层组设置层级区间
      if (isBooleanTrue(isLayerGroup) && this.options.layerGroupId) {
        this.iMapApi && this.iMapApi.setLayerZoomRange(this.options.layerGroupId, minzoom, maxzoom);
      } else {
        this.iMapApi && this.iMapApi.setLayerZoomRange(this.id, minzoom, maxzoom, this.options.layerGroupId);
      }
    }

    /**
     * 获取当前图层的数据Features集合
     */

  }, {
    key: 'getFeatures',
    value: function getFeatures() {
      // 获取图层的数据源
      var layerSource = this.mapLayer && this.mapLayer.source;
      var source = this.iMapApi.getSource(layerSource);
      // 解析数据集合
      var features = [];
      if (source && source._data) {
        return getSourceFeatures(source._data);
      }
      return features;
    }

    /**
     * 设置当前图层的数据Features集合
     * @param {Array} features 待覆盖的Features数据集合
     */

  }, {
    key: 'setFeatures',
    value: function setFeatures(features) {
      // 获取图层的数据源
      var layerSource = this.mapLayer && this.mapLayer.source;
      var source = this.iMapApi.getSource(layerSource);
      if (source) {
        var sourceFeatures = getSourceFeatures(features);
        source.setData(this.turf.featureCollection(sourceFeatures));
      }
    }

    /**
     * 追加当前图层的数据Features集合
     * @param {Array} features 待添加的Features要素数组集合
     */

  }, {
    key: 'addFeatures',
    value: function addFeatures(features) {
      // 获取当前图层的数据
      var currentFeatures = this.getFeatures();
      // 待追加的数据
      var appendFeatures = getSourceFeatures(features);
      // 更新数据集合
      this.setFeatures(currentFeatures.concat(appendFeatures));
    }

    /**
     * 获取当前图层的指定Id的Feature要素
     * @param {String} id Feature要素的唯一Id
     */

  }, {
    key: 'getFeatureById',
    value: function getFeatureById(id) {
      if (!id) {
        return null;
      }
      var features = this.getFeatures();
      var feature = find(features, { id: id });
      return feature || null;
    }

    /**
     * 获取当前图层的指定属性值匹配的Features要素集合
     * @param {String} key 待匹配的Property名
     * @param {Any} value 待匹配的值
     */

  }, {
    key: 'getFeaturesByProperty',
    value: function getFeaturesByProperty(key, value) {
      if (!key || !value) {
        return [];
      }
      var features = this.getFeatures();
      var featureCollection = filter(features, function (f) {
        return f.properties[key] === value;
      });
      return featureCollection || [];
    }

    /**
     * 根据屏幕坐标查询当前图层的Features要素集合
     * @param {Point} point 屏幕坐标点或BBOX范围
     * @param {Object} options 查询的参数条件
     * @param {Boolean} isLayerGroup 是否查询范围为图层所属的图层组
     */

  }, {
    key: 'queryFeaturesByPoint',
    value: function queryFeaturesByPoint(point) {
      var _this3 = this;

      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var isLayerGroup = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      if (!point) {
        return [];
      }

      var resultFeatures = [];
      // 判断是否整个图层组进行查询
      if (isBooleanTrue(isLayerGroup) && this.options.layerGroupId) {
        resultFeatures = this.iMapApi.queryRenderedFeatures(this.options.layerGroupId, point, options);
      } else {
        resultFeatures = this.iMapApi.queryRenderedFeatures(this.id, point, options, this.options.layerGroupId);
      }
      // 获取当前图层的数据集合进行比对转换
      var featureCollection = this.getFeatures();
      var features = [];
      resultFeatures && resultFeatures.map(function (feature) {
        filter(featureCollection, function (f) {
          var isGeometry = _this3.turf.booleanEqual(feature, f);
          if (isGeometry && JSON.stringify(f.properties || {}) === JSON.stringify(feature.properties)) {
            features.push(f);
          }
        });
      });
      return features;
    }

    /**
     * 更新当前图层指定的Feature要素的Properties属性集合
     * @param {Feature} feature 待更新的Feature要素
     * @param {Feature} properties 待更新的Properties集合
     * @param {Boolean} merge 是否采用合并模式
     */

  }, {
    key: 'updateFeatureByProperties',
    value: function updateFeatureByProperties(feature) {
      var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      var merge = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

      var features = this.getFeatures();
      var index = features.indexOf(feature);
      if (index !== -1) {
        if (isBooleanTrue(merge)) {
          features[index].properties = assign({}, features[index].properties, properties);
        } else {
          features[index].properties = properties;
        }
        // 更新数据集合
        this.setFeatures(features);
      }
    }

    /**
     * 更新当前图层指定的Feature要素的Geometry属性空间坐标
     * @param {Feature} feature 待更新的Feature要素
     * @param {Coordinates} coordinates 待更新的空间坐标数据
     */

  }, {
    key: 'updateFeatureByGeometry',
    value: function updateFeatureByGeometry(feature, coordinates) {
      var features = this.getFeatures();
      var index = features.indexOf(feature);
      if (index !== -1) {
        features[index].geometry.coordinates = coordinates;
        // 更新数据集合
        this.setFeatures(features);
      }
    }

    /**
     * 删除当前图层的指定Feature要素数据
     * @param {Feature} feature 待删除的Feature要素
     */

  }, {
    key: 'removeFeature',
    value: function removeFeature(feature) {
      var features = this.getFeatures();
      var deleteFeatures = getSourceFeatures(feature);
      var newFeatures = remove(features, function (f) {
        return deleteFeatures.indexOf(f) === -1;
      });
      // 更新数据集合
      this.setFeatures(newFeatures);
    }

    /**
     * 删除当前图层的指定Id的Feature要素数据
     * @param {String} id 待删除的Feature要素唯一Id
     */

  }, {
    key: 'removeFeatureById',
    value: function removeFeatureById(id) {
      var _this4 = this;

      var ids = isArray(id) ? id : [id];
      ids && ids.map(function (key) {
        var feature = _this4.getFeatureById(key);
        feature && _this4.removeFeature(feature);
      });
    }

    /**
     * 删除当前图层的指定属性值匹配的Features要素集合
     * @param {String} key 待匹配的Property名
     * @param {Any} value 待匹配的值
     */

  }, {
    key: 'removeFeatureByProperty',
    value: function removeFeatureByProperty(key, value) {
      var features = this.getFeaturesByProperty(key, value);
      features && this.removeFeature(features);
    }

    /**
     * 清除当前图层的数据集合
     */

  }, {
    key: 'clearFeatures',
    value: function clearFeatures() {
      // 获取图层的数据源
      var layerSource = this.mapLayer && this.mapLayer.source;
      var source = this.iMapApi.getSource(layerSource);
      // 清空数据
      source && source.setData(this.turf.featureCollection([]));
    }

    /**
     * 获取指定Id的Feature要素存储[feature-state]对象
     * @param {String} id Feature要素的唯一Id
     */

  }, {
    key: 'getFeatureState',
    value: function getFeatureState(id) {
      var map = this.iMapApi.map;
      return id && map && map.getFeatureState({
        source: this.mapLayer.source,
        sourceLayer: this.mapLayer.sourceLayer,
        id: id
      });
    }

    /**
     * 设置指定Id的Feature要素存储[feature-state]对象
     * @param {String} id Feature要素的唯一Id
     * @param {Object} state 存储Feature要素的[feature-state]对象
     */

  }, {
    key: 'setFeatureState',
    value: function setFeatureState(id) {
      var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      var map = this.iMapApi.map;
      id && map && map.setFeatureState({
        source: this.mapLayer.source,
        sourceLayer: this.mapLayer.sourceLayer,
        id: id
      }, state);
    }

    /**
     * 清空所有或删除指定Id的Feature要素存储[feature-state]对象
     * @param {String} id Feature要素的唯一Id，未指定则清空所有Feature要素
     * @param {String} key 指定待删除的[feature-state]对象键名
     */

  }, {
    key: 'removeFeatureState',
    value: function removeFeatureState() {
      var id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
      var key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

      var map = this.iMapApi.map;
      // 判断是否设置Feature要素的Id
      if (!id) {
        map.removeFeatureState({
          source: this.mapLayer.source
        });
      } else {
        // 判断是否指定具体的待删除[feature-state]键名
        map.removeFeatureState({
          source: this.mapLayer.source,
          sourceLayer: this.mapLayer.sourceLayer,
          id: id
        }, key);
      }
    }

    /**
     * 获取当前图层的Feature数据集的几何矩形范围
     */

  }, {
    key: 'getLayerBounds',
    value: function getLayerBounds() {
      var features = this.getFeatures();
      return isNotEmptyArray(features) && this.iMapApi.getFeaturesToBounds(features);
    }

    /**
     * 设置当前图层缩放到最大的合适层级
     */

  }, {
    key: 'setLayerToMaxZoom',
    value: function setLayerToMaxZoom() {
      var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

      var features = this.getFeatures();
      return this.iMapApi.boundsToFeatures(features, options);
    }
  }]);

  return BasicLayerClass;
}(BasicMapApi);

export default BasicLayerClass;

// 验证不透明度是否正确并纠正返回正确的数值
export var getCheckOpacity = function getCheckOpacity(opacity) {
  var _value = isNumeric(opacity) ? Number(opacity) : 1;
  _value > 1 && (_value = 1);
  _value < 0 && (_value = 0);
  return _value;
};

// 设置图层的Paint透明度属性
export var setLayerPaintOpacity = function setLayerPaintOpacity(paint, properties, ratio) {
  isString(properties) && (properties = [properties]);
  var copyPaint = cloneDeep(paint);
  properties && properties.map(function (key) {
    if (copyPaint[key] && isNumeric(copyPaint[key])) {
      var opacity = getCheckOpacity(copyPaint[key]);
      copyPaint[key] = round(opacity * ratio, 2);
    }
  });
  return copyPaint;
};

// 获取图层Source数据源的Feature集合
export var getSourceFeatures = function getSourceFeatures(data) {
  var features = [];
  if (data && data.type) {
    switch (data.type) {
      case 'Feature':
        features.push(data);
        break;
      case 'FeatureCollection':
        features.push.apply(features, _toConsumableArray(data.features));
        break;
    }
  } else if (isNotEmptyArray(data)) {
    features.push.apply(features, _toConsumableArray(data));
  }
  return features;
};