import React from 'react';
import ReactDOM from 'react-dom';
import { map } from '../mapContext';
import { tipOptions } from '../utils/config';
import { popupOptions, clusterOptions } from '../utils/config';
import { createDeviceIcon, MutipleDeviceAndPlace, SingleDevice, createJudgementPlaceIcon } from '../utils/overlayer';
import ResourceLayer from './ResourceLayer';
import * as L from 'leaflet';
import 'leaflet.zv.markercluster';
import 'leaflet.zv.markercluster/dist/MarkerCluster.Default.css';
import 'leaflet.zv.markercluster/dist/MarkerCluster.css';
import base64 from '../base64';
import { LMConfig } from '@zenview/micro-basic-library'
const { PlaceIcon } = base64;
let nearByPointsCache = {};

@map
class ClusterLayer extends React.Component {
  constructor(props) {
    super(props);
    this.types = null;
    this.status = null;
    this.curPopupMarker = null;
    this.singPopupDom = document.createElement("div");
    this.mutiplePopupDom = document.createElement("div");
    this.singPopupDom.className = "marker-popup-single-content";
    this.mutiplePopupDom.className = "marker-popup-mutiple-content arrow-map-layout";
    this.state = {
      points: props.points || null,
      isDataChange: false,
      mutiplePoints: [],
      singlePoint: {}
    };
    this.clusterMarkers = L.markerClusterGroup(clusterOptions).addTo(this.props.map);
    this.featureGroup = L.featureGroup();
  }
  static getDerivedStateFromProps(props, state) {
    if (props.points && props.points !== state.points) {
      return { isDataChange: true, points: props.points };
    }
    return null;
  }
  componentDidMount() {
    this._initMapCluster();
    if (Array.isArray(this.state.points) && this.state.points.length > 0) {
      this._initMarker(this.state.points);
    }
  }
  componentDidUpdate() {
    if (this.state.isDataChange) {
      this.setState({ isDataChange: false });
      if (Array.isArray(this.state.points) && this.state.points.length > 0) {
        this._initMarker(this.state.points);
      } else {
        this.clusterMarkers.clearLayers();
        this.featureGroup.clearLayers();
      }
    }
  }
  componentWillUnmount() {
    //this.singPopupDom.remove();
    this.mutiplePopupDom.remove();
    this.clusterMarkers.clearLayers();
    this.featureGroup.clearLayers();
    this.featureGroup = null;
    this.clusterMarkers = null;
    this.singPopupDom = null;
    this.mutiplePopupDom = null;
    this.curPopupMarker = null;
  }
  _initMapCluster() {
    const { mapMethods, map } = this.props;
    this.clusterMarkers.on("clusterclick", e => {
      if(this.curPopupMarker === e.layer) return;
      let zoom = mapMethods.getZoom();
      if (zoom === LMConfig.LMapConfig.layerOptions.maxZoom) {
        const markers = e.layer.getAllChildMarkers();
        const points = markers.map(v => v.__extData);
        this.setState({ mutiplePoints: points });
        const popup = L.popup(popupOptions).setContent(this.mutiplePopupDom);
        e.layer.unbindPopup();
        e.layer.bindPopup(popup).openPopup();
        this.curPopupMarker = e.layer;
      } else {
        e.layer.zoomToBounds({padding: [20, 20]});
      }
    });
    map.on("click", () => {
      if (this.curPopupMarker) {
        this.curPopupMarker.closePopup();
        this.curPopupMarker = null;
      }
    });
  }

  _initMarker(points) {
    const { autoView = true } = this.props;
    this.featureGroup.clearLayers();
    this.clusterMarkers.clearLayers();
    const markers = [];
    let marker;
    for (let i = 0, l = points.length; i < l; i++) {
      let point = points[i];
      if(point.pointDataType === 'place'){
        marker = this.createPlaceMarker(point);
      }else{
        if (!point.latitude || !point.longitude) {
          continue;
        }
        if (this.types && this.types.indexOf(point.deviceType) === -1) {
          continue;
        }
        if (this.status && this.status.indexOf(point.deviceStatus) === -1) {
          continue;
        }
        marker = this.createMarker(point);
      }
      this.featureGroup.addLayer(marker);
      markers.push(marker);
    }
    this.clusterMarkers.addLayers(markers);
    this.props.createCallback && this.props.createCallback();
    if (autoView) {
      this.mapReset();
    }
  }

  getAllClusterPoints() {
    return this.clusterMarkers.getLayers().map(v => v.__extData);
  }

  _getMarkerPopup(point) {
    const { renderIconGroup } = this.props;
    ReactDOM.render(<SingleDevice point={{...point, deviceName: point.deviceName || point.areaName}} renderIconGroup={renderIconGroup} />,
      this.singPopupDom
    );
    return L.popup(Object.assign({}, popupOptions, {
      offset: L.point(0, renderIconGroup ? 100 : -10)
    })).setContent(this.singPopupDom);
  }

  createPlaceMarker(point){
    const {  markerClick } = this.props;
    // 创建场所点位
    let marker = new L.Marker(L.latLng(point.latitude, point.longitude), {
      icon: createJudgementPlaceIcon(PlaceIcon)
    });
    marker.__extData = point;
    marker.bindTooltip(point.areaName, tipOptions)
    // marker.on("mouseover", e => {
      // !e.target.isPopupOpen() && e.target.bindPopup(this._getMarkerPopup(point)).togglePopup();
    // });
    // marker.on("mouseout", e => {
    //   if(e.originalEvent.relatedTarget.className === "leaflet-popup-content-wrapper") return;
    //   e.target.closePopup().unbindPopup();
    // });

    if (markerClick) {
      marker.on("click", () => {
        markerClick(point);
      });
    }

    return marker;
  }

  createMarker(point) {
    const {  markerClick } = this.props;
    let marker = new L.Marker(L.latLng(point.latitude, point.longitude), {
      icon: createDeviceIcon(point)
    });
    marker.__extData = point;
    marker.bindTooltip(point.deviceName, tipOptions)
    // marker.on("mouseover", e => {
      /*const points = this.computedNearbyPoints(point);
      const options = popupOptions;
      let popup;
      if (points.length > 1) {
        this.setState({ mutiplePoints: points });
        popup = L.popup(options).setContent(this.mutiplePopupDom);
        marker.bindPopup(popup).togglePopup();
      } else {
        this.setState({ singlePoint: point });
        options.offset = L.point(0, renderIconGroup ? 60 : -10);
        popup = L.popup(options).setContent(this.singPopupDom);
      }*/
      // !e.target.isPopupOpen() && e.target.bindPopup(this._getMarkerPopup(point)).togglePopup();
    // });
    // marker.on("mouseout", e => {
    //   if(e.originalEvent.relatedTarget.className === "leaflet-popup-content-wrapper") return;
    //   e.target.closePopup().unbindPopup();
    // });

    if (markerClick) {
      marker.on("click", () => {
        markerClick(point);
      });
    }

    return marker;
  }
  computedNearbyPoints(point) {
    if (nearByPointsCache[point.id]) {
      return nearByPointsCache[point.id];
    }
    let nearPoints = [];
    const { map } = this.props;
    const points = this.getAllClusterPoints();
    const centerPoint = L.latLng(point.latitude, point.longitude);
    for (let i = 0, l = points.length; i < l; i++) {
      if (
        points[i].latitude &&
        points[i].longitude &&
        map.distance(centerPoint, L.latLng(points[i].latitude, points[i].longitude)) <= 20
      ) {
        nearPoints.push(points[i]);
      }
    }
    nearByPointsCache[point.id] = nearPoints;
    return nearPoints;
  }
  showCustomMarker = (types, status) => {
    nearByPointsCache = {};
    this.status = status;
    this.types = types;
    this._initMarker(this.state.points);
  };

  mapReset() {
    const bounds = this.featureGroup.getBounds();
    if (bounds.isValid()) {
      this.props.map.fitBounds(bounds);
    }
  }
  render() {
    const { /*singlePoint,*/ mutiplePoints } = this.state;
    const { hasFilterResource, excludeTypes, hideFeatures, children } = this.props;
    /*{ReactDOM.createPortal(
          <SingleDevice point={singlePoint} renderIconGroup={this.props.renderIconGroup} />,
          this.singPopupDom
        )}*/
    return (
      <>
        {hasFilterResource && (
          <ResourceLayer
            excludeTypes={excludeTypes}
            hideFeatures={hideFeatures}
            getPopupContainer={this.props.getPopupContainer}
            showCustomMarker={this.showCustomMarker}
          >
            {children}
          </ResourceLayer>
        )}
        {ReactDOM.createPortal(
          <MutipleDeviceAndPlace
            points={mutiplePoints}
            renderIconGroup={this.props.renderIconGroup}
            itemClick={this.props.markerClick}
          />,
          this.mutiplePopupDom
        )}
      </>
    );
  }
}
export default ClusterLayer;
