import DataUtils from '../utils/DataUtils';
import GeogUtils from '../utils/GeogUtils';

/**
 * 定义地图方法提供类
 */
export default class MapProvider {
  constructor() { }

  /**
   * 获取地图对象
   *
   * @returns {Object}
   */
  static getMap() {
    return window.gisMap;
  }

  /**
   * 设置鼠标样式
   * @param {Object} map -地图对象
   * @param {String} cursor -鼠标样式
   */
  static setCursor(map, cursor = '') {
    if (map.getCanvas().style.cursor !== 'crosshair') {
      map.getCanvas().style.cursor = cursor;
    }
  }

  /**
   * 绑定仅一次响应事件
   * @param {Object} map -地图对象
   * @param {String} name -事件
   * @param {function} func -函数对象
   */
  static onceEvent(map, name, func) {
    map.once(name, func);
  }

  /**
   * 绑定事件
   * @param {Object} map -地图对象
   * @param {String} name -事件
   * @param {function} func -函数对象
   */
  static onEvent(map, name, func) {
    map.on(name, func);
  }

  /**
   * 解除事件绑定
   * @param {Object} map -地图对象
   * @param {String} name -事件
   * @param {function} func -函数对象
   */
  static offEvent(map, name, func) {
    map.off(name, func);
  }

  /**
   * 适应边界框
   * @param {Object} map -地图对象
   * @param {Array} bbox -边界框
   * @param {Number} zoom -缩放层级
   * @param {Boolean} jump -是否直接定位
   */
  static fitBounds(map, bbox, zoom = null, jump = false) {
    const currZoom = map.getZoom();

    if (jump) {
      if (zoom) {
        map.fitBounds(bbox, {
          animate: false,
          padding: 25,
          //maxZoom: zoom
          maxZoom: zoom >= currZoom ? zoom : currZoom
        });
      } else {
        map.fitBounds(bbox, {
          animate: false,
          padding: 25,
        });
      }
    } else {
      if (zoom) {
        map.fitBounds(bbox, {
          padding: 25,
          //maxZoom: zoom
          maxZoom: zoom >= currZoom ? zoom : currZoom
        });
      } else {
        map.fitBounds(bbox, {
          padding: 25,
        });
      }
    }
  }

  /**
   * 定位
   * @param {Object} map -地图对象
   * @param {Array} lonLat -经纬度
   * @param {Number} zoom -缩放层级
   */
  static locate(map, lonLat, zoom) {
    this.flyTo(map, lonLat, zoom);
  }

  /**
   * 飞行至中心点
   * @param {Object} map -地图对象
   * @param {Array} lonLat -经纬度
   * @param {Number} zoom -缩放层级
   */
  static flyTo(map, lonLat, zoom) {
    map = DataUtils.default(map, this.getMap());
    zoom = DataUtils.default(zoom, map.getZoom());
    zoom = Math.max(zoom, map.getZoom());

    map.flyTo({
      center: lonLat,
      speed: 1.0,
      zoom: zoom,
      essential: true, // 动画
      easing: (t) => {
        return t; // 飞行时间进度, (t === 1) 即飞行结束
      }
    }, {
      // eventData 自定义的事件属性
      moveend: 'FLYTO_END'
    });
  }

  /**
   * 跳至中心点
   * @param {Object} map -地图对象
   * @param {Array} lonLat -经纬度
   * @param {Number} zoom -缩放层级
   */
  static jumpTo(map, lonLat, zoom) {
    map = DataUtils.default(map, this.getMap());
    zoom = DataUtils.default(zoom, map.getZoom());
    zoom = Math.max(zoom, map.getZoom());

    map.jumpTo({
      center: lonLat,
      zoom: zoom
    });
  }

  /**
   * 选中要素
   * @param {Object} map -地图对象
   * @param {String} sourceId -数据源Id
   * @param {String} featureId -要素ID
   * @param {Boolean} isHover -是否选中
   */
  static hoverFeature(map, sourceId, featureId, isHover = true) {
    map.setFeatureState({
      source: sourceId,
      id: featureId
    }, {
      hover: isHover
    });
  }

  /**
   * 缩放到要素
   * @param {Object} map -地图对象
   * @param {Object} fc -要素集
   * @param {Boolean} zoom -缩放层级
   */
  static zoomToFeatures(map, fc, zoom = 17, jump=false) {
    // 计算边界盒
    let bbox = GeogUtils.calcBBox(fc);
    // 缩放至边界
    this.fitBounds(map, bbox, zoom, jump);
  }
}
