/* 
TODO 修改完成
*/

import React from 'react';
import Map from '../../instance';
import { Provider } from '../../mapContext';
import * as L from 'leaflet';
import _ from 'lodash';
import '../../style/map.less';

import { BaseStore } from '@zenview/micro-basic-library';
import { uuid, resizeObserver } from '@zenview/micro-utils';

// const { Utils, BaseStore } = window;

export default class MapComponent extends React.Component {
  constructor(props) {
    super(props);
    this.IbsMapDom = React.createRef();
    this.ele = document.createElement('div');
    this.ele.id = uuid();
    this.mapMethods = {};
    this.map = {};
    this.state = {
      isInit: false,
    };
  }
  componentDidMount() {
    this.IbsMapDom.current.appendChild(this.ele);
    const { centerPoint = '', zoomLevelCenter = 6 } = BaseStore.app.systemConfig;
    const { mapConfig = { scrollWheelZoom: true }, mapOptions } = this.props;

    if (centerPoint) {
      const center = centerPoint.split(',');
      this.mapConfig = { center: L.latLng({ lat: center[1], lng: center[0] }), zoom: zoomLevelCenter, ...mapConfig };
      this.map = new Map();
      this.map.__createMap(this.ele, mapConfig, mapOptions);
    } else {
      this.mapConfig = { zoom: zoomLevelCenter, ...mapConfig };
      this.map = new Map(this.ele, mapConfig);
      this.map.__createMap(this.ele, mapConfig, mapOptions);
    }
    this.mapConfig = Object.assign({}, this.map.mapConfig, this.mapConfig);

    this.mapConfig.latlng = this.mapConfig.center;
    this.mapConfig.center = Array.isArray(this.mapConfig.latlng) ? this.mapConfig.latlng : [this.mapConfig.latlng.lat, this.mapConfig.latlng.lng];

    Object.getOwnPropertyNames(this.map.__proto__).forEach((key) => {
      if (key !== 'constructor' && key.indexOf('__') === -1 && typeof this.map[key] === 'function') {
        this.mapMethods[key] = this.map[key].bind(this.map);
      }
    });

    this.mapMethods.mapReset = this.mapReset;
    this.mapMethods.setSelectCursor = this.setSelectCursor;
    this.mapMethods.resetCursor = this.resetCursor;

    this.props.initMap && this.props.initMap(this.map);
    if (!this.mapConfig.scrollWheelZoom && this.IbsMapDom.current) {
      this.IbsMapDom.current.addEventListener('mousewheel', this.ctrlMosueWheel, { passive: false });
    }
    if (!this.isUnmount) {
      this.setState({ isInit: true });
    }
    resizeObserver.createResizeObserver(this.IbsMapDom.current, this.invalidateSize);
  }

  invalidateSize = () => {
    if (this.map) {
      this.map.map.invalidateSize();
    }
  };

  ctrlMosueWheel = (e) => {
    if (!this.mapConfig.scrollWheelZoom && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      this.debounced && this.debounced.cancel();
      this.debounced = _.debounce(() => this.map.setZoom(this.map.getZoom() + (e.deltaY > 0 ? -1 : 1)), 100);
      this.debounced();
    }
  };

  componentWillUnmount() {
    clearTimeout(this.timer);
    resizeObserver.unResizeObserver(this.IbsMapDom.current);
    this.debounced && this.debounced.cancel();
    this.IbsMapDom.current.removeEventListener('mousewheel', this.ctrlMosueWheel, { passive: false });
    this.isUnmount = true;
    this.IbsMapDom.current.removeChild(this.ele);
    this.map.destroy();
    this.map = null;
    this.mapMethods = null;
    this.IbsMapDom = null;
  }

  getProviderValue() {
    return {
      map: this.map.map,
      mapMethods: this.mapMethods,
      mapConfig: this.mapConfig,
    };
  }

  mapReset = () => {
    this.map.setZoomAndCenter(this.mapConfig.zoom, this.mapConfig.center);
  };

  setSelectCursor = () => {
    this.IbsMapDom.current.classList.add('map-select-cursor');
  };

  resetCursor = () => {
    this.IbsMapDom.current.classList.remove('map-select-cursor');
  };

  render() {
    const { className = '', style = {} } = this.props;
    return (
      <Provider value={this.getProviderValue()}>
        <div className="leaflet-wrapper-layout">
          <div className={`leaflet-map-wrapper ${className}`} ref={this.IbsMapDom} style={style}>
            {this.state.isInit && this.map.map && this.props.children}
          </div>
        </div>
      </Provider>
    );
  }
}
