import React from 'react';
import { render } from 'react-dom';
import { connect } from 'dva';
import $ from 'jquery';
import isEqual from 'lodash/isEqual';
import cls from 'classnames';
import Search from './Search';
import Filter from './Filter';
import People from './People';
import Vehicle from './Vehicle';
import Customer from './Customer';
import TableInfo from './TableInfo';
import RealVideo from './RealVideo';
import EleDiagram from './EleDiagram';
import ClusterMarker from './ClusterMarker';
import RunStatus from './RunStatus';
import CheckInfo from './CheckInfo';
import PowerPayload from './PowerPayload';
import {
  DispatchDataMap,
  RunStatusEnum,
  VehicleStatusMap,
  featureEnum,
  PeopleStatusEnum,
  VehicleStatusEnum,
} from '../constants';
import MarkerIcon from './MarkerIcon';
import PlayerModal from './PlayerModal';
import MapTools from './MapTools';
import styles from './index.less';

import 'echarts/lib/chart/line';
import 'echarts/lib/chart/pie';
import 'echarts/lib/chart/radar';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/grid';
import 'echarts/lib/component/legend';
import 'echarts/lib/component/title';
import * as _ from 'lodash';

// 暂时使用固定的 DOM 节点
let mapNode;

@connect(({ screen }) => {
  const dataList = [].concat(
    screen.vehicleList,
    screen.peopleList,
    screen.customerList,
  );
  return {
    // dataList: screen.search ? dataList.filter(item => item.id === screen.search) : dataList,
    dataList,
    diffDataList: screen.diffDataList,
    search: screen.search,
    liveVideoShow: screen.liveVideoShow,
    liveVideo: screen.liveVideo,
    hasKey: screen.hasKey,
    selectedPoint: screen.selectedPoint,
    company: screen.company,
    features: screen.features,
    filterTypes: screen.filterTypes,
    area: screen.area,
    photovoltaic: screen.photovoltaic,
    energyStorage: screen.energyStorage,
    chargingPile: screen.chargingPile,
    lateLy30Charging: screen.lateLy30Charging,
    peopleVideo: screen.peopleVideo
  };
})
class AMapCom extends React.PureComponent {
  mapInstance = null;

  /**
   * 详细标记点的弹窗
   */
  popInfoWindow = null;

  /**
   * 聚合标记点的弹窗
   */
  popInfoWindow = null;

  defaultZoom = 5;
  defaultCenter = [105.397428, 34.3];

  /**
   * 是否要隐藏 tableInfoWindow
   */
  shouleHidden = true;
  hiddenTimer = null;

  // constructor(props) {
  //   super(props)
  //   this.defaultCenter = [105.397428, props.isNormal ? 35.40923 : 34.3]
  // }

  state = {
    data: [],
    selected: null,
    inited: false,
  };

  componentWillMount() {
    if (!document.querySelector(`.${styles.mapBox}`)) {
      mapNode = document.createElement('div');
      mapNode.className = cls(styles.mapBox, { 'normal-map': this.props.isNormal });
      document.body.appendChild(mapNode);
    }
  }

  async componentDidMount() {
    this.createMap();
    this.initMapUI();
    this.bindEvent();

    await this.fetchDistData();

    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleFilterTypes',
      payload: [DispatchDataMap.customer]
    });

    if (process.env.NODE_ENV === 'development') return
    // 延迟执行
    setTimeout(() => {
      this.intervalFetchDistData();
    }, 30 * 1000);
  }

  componentDidUpdate(prevProps) {
    const {
      dataList,
      search,
      selectedPoint,
      filterTypes,
      company,
      features,
      area,
    } = this.props;

    if (mapNode && prevProps.width !== this.props.width) {
      mapNode.style.width = `${this.props.width}px`;
    }

    if (dataList && dataList.length) {
      // 根据搜索内容定位
      if (search && search !== prevProps.search) {
        const searchItem = dataList.find(item => item.id === search);
        // FIXME: 统一逻辑
        this.clear();
        searchItem && this.moveToPosition(searchItem.position);
        setTimeout(() => {
          this.renderPopInfoWindow(searchItem);
        }, 500);
      }
      // 点击指定的点定位
      if (selectedPoint && !isEqual(selectedPoint, prevProps.selectedPoint)) {
        const { type, id } = selectedPoint;
        const point = dataList.find(
          item => item._id === id && item.type === type,
        );
        if (point) {
          this.clear();
          this.moveToPosition(point.position);
          setTimeout(() => {
            this.renderPopInfoWindow(point);
          }, 500);
        }
      }

      // 过滤点
      if (
        !_.isEqual(filterTypes, prevProps.filterTypes) ||
        !_.isEqual(company, prevProps.company) ||
        !_.isEqual(features, prevProps.features) ||
        !_.isEqual(area, prevProps.area)
      ) {
        this.filterData();
      }
    }
  }

  componentWillUnmount() {
    this.clearTimer();
  }

  initMapUI = () => {
    const { scale, isNormal } = this.props;
    // marker 聚合
    this.initMarkerCluster();

    const right = isNormal ? 850 : 690;
    // 工具-罗盘
    this.mapInstance.addControl(
      new AMap.ControlBar({
        theme: 'dark',
        showZoomBar: false,
        position: {
          bottom: '110px',
          right: `${right * scale}px`,
        },
      }),
    );

    // 工具-缩放
    AMapUI.loadUI(['control/BasicControl'], BasicControl => {
      const right = isNormal ? 920 : 720;
      this.mapInstance.addControl(
        new BasicControl.Zoom({
          //内置的dark主题
          theme: 'dark',
          //左下角
          position: {
            bottom: '106px',
            right: `${right * scale}px`,
          },
          showZoomNum: false,
        }),
      );
    });
  };

  bindEvent = () => {
    // 地图 Marker 选择效果
    $('.amap-maps').on('click', '.amap-marker', function(e) {
      e.stopPropagation();
      $(this)
        .addClass('selected')
        .siblings()
        .removeClass('selected');
    });
    this.mapInstance.on('click', () => {
      $('.amap-marker').removeClass('selected');
    });
    // $('body').on('click', () => {
    //   this.clear()
    // })
  };

  // TODO: 性能太差。。。暂时废弃，后续再调研下该方案
  __initMarkerList = MarkerList => {
    const markerList = new MarkerList({
      map: this.mapInstance,
      markerEvents: ['click'],
      selectedClassNames: 'selected',
      listContainer: null,
      makeSelectedEvents: null,
      getListElement: null,
      getDataId: function(dataItem) {
        //返回数据项的Id
        return dataItem.id;
      },
      getPosition: function(dataItem) {
        //返回数据项的经纬度，AMap.LngLat实例或者经纬度数组 [121.710266, 31.035553]
        return [dataItem.position[0], dataItem.position[1]];
      },
      getInfoWindow: this.renderPopInfoWindow,
      getMarker: (dataItem, context, recycledMarker) => {
        const content = this.renderDetailMarker(dataItem);

        if (recycledMarker) {
          recycledMarker.setContent(content);
          recycledMarker.setExtData(dataItem);
          return recycledMarker;
        }
        //返回一个新的Marker
        return new AMap.Marker({
          anchor: 'center',
          extData: dataItem,
          content,
        });
      },
    });
    this.markerList = markerList;
    this.markerList.render(this.props.dataList);
  };

  /**
   * 初始化标记点
   */
  initMarkerList = () => {
    console.log('init marker list ==>', this.props.dataList.length)
    const markers = this.createMarkers(this.props.dataList);
    this.markerCluster.setMarkers(markers);
    this.markerList = markers;
  };

  /**
   * 更新标记点
   */
  updateMarkerList = diffDataList => {
    const diffIds = diffDataList.map(item => item.id);
    const markers = this.createMarkers(diffDataList);
    const currentMarkerList = [];
    const removedMarkers = [];
    const { filterTypes, features } = this.props;
    const showAIOps = features.includes(featureEnum.aiops);
    const isTargetType = filterTypes.includes(DispatchDataMap.people) || filterTypes.includes(DispatchDataMap.vehicle);
    // 选择智慧运维，并且选择了人员和车辆时才出发更新
    const shouldUpdate = showAIOps && isTargetType
    if (shouldUpdate) {
      this.markerList.forEach(marker => {
        const { id } = marker.getExtData();
        if (diffIds.includes(id)) {
          removedMarkers.push(marker);
        } else {
          currentMarkerList.push(marker);
        }
      });
      this.markerCluster.removeMarkers(removedMarkers);
      this.markerCluster.addMarkers(markers);
      this.markerList = currentMarkerList.concat(markers);
      return;
    }
    this.markerList = this.markerList.concat(markers)
  };

  /**
   * 基于数据创建标记点
   */
  createMarkers = data => {
    return data.map(item => {
      const content = this.renderDetailMarker(item);
      const marker = new AMap.Marker({
        position: item.position,
        anchor: 'center',
        extData: item,
        content,
      });

      marker.on('click', () => {
        this.forcusMarker(marker);
        this.onClickMarker(item);
      });
      return marker;
    });
  };

  /**
   * 初始化聚合插件
   */
  initMarkerCluster = () => {
    this.markerCluster = new AMap.MarkerClusterer(this.mapInstance, [], {
      gridSize: 90,
      renderClusterMarker: this.renderClusterMarker,
    });
    this.markerCluster.on('click', () => {
      this.clear();
    });
  };

  renderClusterMarker = ({ count, marker, markers }) => {
    const infoMarkers = markers.map(item => item.getExtData());
    const content = this.renderDom(
      <ClusterMarker
        count={count}
        markers={infoMarkers}
        onMouseEnter={() => this.onHoverClusterMarker(marker, infoMarkers)}
        onMouseLeave={this.delayCloseTableInfoWindow}
      />,
    );
    marker.setAnchor('center');
    marker.setzIndex(100);
    marker.setContent(content);
  };

  onHoverClusterMarker = (marker, markers) => {
    this.clearHiddenTimer();
    // 防止自动移动地图后误触发
    if (this.forcusFlag) {
      return;
    }
    const position = marker.getPosition();
    const html = this.renderDom(
      <TableInfo
        data={markers}
        clickTableInfoDetail={item => this.clickTableInfoDetail(item)}
        onMouseEnter={() => {
          this.shouleHidden = false;
          this.tableInfoWindow.open(this.mapInstance, position);
        }}
        onMouseLeave={() => {
          this.shouleHidden = true;
          this.closeTableInfoWindow();
        }}
      />,
    );
    if (!this.tableInfoWindow) {
      this.tableInfoWindow = this.createInfoWindow(
        html,
        new AMap.Pixel(25, -40),
      );
    }
    this.tableInfoWindow.setContent(html);
    this.tableInfoWindow.open(this.mapInstance, position);
  };

  delayCloseTableInfoWindow = () => {
    this.clearHiddenTimer();
    this.hiddenTimer = setTimeout(() => {
      if (this.shouleHidden) {
        this.closeTableInfoWindow();
      }
    }, 300);
  };

  clearHiddenTimer = () => {
    if (this.hiddenTimer) {
      clearTimeout(this.hiddenTimer);
      this.hiddenTimer = null;
    }
  };

  forcusMarker = marker => {
    this.forcusFlag = true;
    marker.setTop(false);
    this.mapInstance.setCenter(marker.getPosition());
    this.forcusFlag = false;
  };

  /**
   * 移动到指定位置
   */
  moveToPosition = (position = []) => {
    this.mapInstance.setZoomAndCenter(18, position);
  };

  closeTableInfoWindow = () => {
    this.tableInfoWindow && this.tableInfoWindow.close();
  };

  closePopInfoWindow = () => {
    this.popInfoWindow && this.popInfoWindow.close();
  };

  /**
   * 请求地图聚合数据，人、车、户号
   */
  fetchDistData = async () => {
    const { dispatch } = this.props;
    await Promise.all([
      dispatch({
        type: 'screen/fetchVehiclePeople',
      }),
      dispatch({
        type: 'screen/fetchCustomer',
      })
    ])
    this.initMarkerList();
  };

  /**
   * 轮询请求地图聚合数据，人员、车辆
   */
  intervalFetchDistData = async () => {
    console.log('== begin ==')
    this.clearTimer();
    const { dispatch } = this.props;
    this.timer = setInterval(() => {
      dispatch({
        type: 'screen/fetchVehiclePeople',
      }).then(res => {
        console.log('diff map:', res);
        if (res.length) {
          this.updateMarkerList(res);
        }
      });
    }, 30 * 1000);
  };

  clearTimer = () => {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
  };

  /**
   * 根据类型（人、车、户号）过滤
   */
  filterDataByType = (filters = []) => {
    const markers = this.markerList.filter(item =>
      filters.includes(item.getExtData().type),
    );
    this.markerCluster.setMarkers(markers);
  };

  /**
   * 自定义过滤条件
   */
  filterData = _.debounce(() => {
    console.log('== filterData ==')
    if (!this.markerList || !this.markerList.length) return;
    const { filterTypes, company, features, area } = this.props;

    console.log('== filterTypes ==', filterTypes);
    console.log('== company ==', company);
    console.log('== features ==', features);
    console.log('== area ==', area);

    const markers = this.markerList.filter(marker => {
      const pointData = marker.getExtData();
      // 是否是户号
      const isCustomerNumber = pointData.type === DispatchDataMap.customer;
      // 是否选择了智慧运维
      const showAIOps = features.includes(featureEnum.aiops);

      // 根据点的类型过滤（人、车、户号）
      const showByType =
        (showAIOps && filterTypes.length > 0)
          ? _.includes(filterTypes, pointData.type)
          : isCustomerNumber;

      // 根据是否属于子公司过滤
      let showByCompany = true;
      if (company && (isCustomerNumber || pointData.type === DispatchDataMap.people)) {
        showByCompany = _.includes(pointData.enterprise, company)
      }

      // 根据是否开通某功能过滤
      let showByFeature = true;
      if (features.length > 0 && isCustomerNumber) {
        // 如果只选择了智慧运维
        if (features.length === 1 && showAIOps) {
          showByFeature = true
        } else {
          showByFeature = features.some(item => pointData.features.includes(item));
        }
      }
      // showByFeature =
      // isCustomerNumber ? showByFeature : true;

      // 根据地区过滤
      let showByArea = true;
      const [province, city] = area;
      if (city) {
        showByArea = `${city}` === `${pointData.city}`;
      } else if (province) {
        showByArea = `${province}` === `${pointData.province}`;
      }

      return showByType && showByCompany && showByFeature && showByArea;
    });
    console.log('markers: ', markers.length);
    this.markerCluster.setMarkers(markers);
  }, 400);

  /**
   * 渲染地图标记点，人、车、户号
   */
  renderDetailMarker = (item, selected = false) => {
    const { type, status } = item;
    let gray = false;
    if (type === DispatchDataMap.people) {
      gray = status === PeopleStatusEnum.offline;
    } else if (type === DispatchDataMap.vehicle) {
      gray = status === VehicleStatusEnum.offline;
    }
    const content = this.renderDom(
      <MarkerIcon
        {...item}
        selected={selected}
        gray={gray}
        type={type}
        error={status === RunStatusEnum.error}
      />,
    );
    return content;
  };

  onClickRealVideo = id => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleVideo',
      payload: id,
    });
  };

  onClickEleDiagram = data => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleEleDiagram',
      payload: data,
    });
  };

  onClickRunStatus = id => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleRunStatus',
      payload: id,
    });
  };

  onClickCheckInfo = id => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleCheckInfo',
      payload: id,
    });
  };

  handleCustomerStation = payload => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleCustomerStation',
      payload,
    });
  };

  onClickEnergyChart = data => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleEnergyChart',
      payload: data,
    });
  };

  onClickCheckStatistics = data => {
    const { dispatch } = this.props;
    dispatch({
      type: 'screen/handleCheckStatistics',
      payload: data,
    });
  };

  onChangeSelectedPoint = item => {
    const { dispatch, selectedPoint } = this.props;
    if (selectedPoint === item) {
      return;
    }
    dispatch({
      type: 'screen/handleSelectedPoint',
      payload: item,
    });
  };

  clickTableInfoDetail = item => {
    this.renderPopInfoWindow(item);
    this.mapInstance.setCenter(item.position);
  };

  onLiveVideo = (payload) => {
    return this.props.dispatch({
      type: 'screen/fetchLiveVideos',
      payload,
    });
  };

  showLiveVideo = (videoSource = 'common') => {
    const { liveVideoShow } = this.props;
    this.props.dispatch({
      type: 'screen/showLiveVideo',
      payload: {
        liveVideoShow: !liveVideoShow,
        videoSource,
      },
    });

  };

  handleScale = () => {
    this.mapInstance.setZoomAndCenter(this.defaultZoom, this.defaultCenter);
  };

  handleLocation = () => {
    this.mapInstance.setZoomAndCenter(10, [121.555941, 31.178316]);
  };

  /**
   * 渲染地图点的弹窗
   */
  renderPopInfoWindow = data => {
    const { position, type } = data;
    const {dispatch, isNormal} = this.props;
    let content = <div />;
    let offset = new AMap.Pixel(30, 100);
    let anchor = 'bottom-left'
    const fetchRealData = () => dispatch({type: 'screen/fetchRealPLData'});
    const getPeopleVideoUrl = userId => dispatch({
      type: 'screen/getPeopleVideoUrl',
      payload: {userId}
    })
    switch (type) {
      case DispatchDataMap.people: {
        content = this.renderDom(
          <People
            {...data}
            showLiveVideo={this.showLiveVideo}
            getPeopleVideoUrl={getPeopleVideoUrl}
          />,
        );
        break;
      }
      case DispatchDataMap.vehicle: {
        content = this.renderDom(<Vehicle {...data} />);
        break;
      }
      case DispatchDataMap.customer: {
        offset = new AMap.Pixel(30, -300);
        anchor = 'top-left'
        content = this.renderDom(
          <Customer
            {...data}
            onClickVideo={this.showLiveVideo}
            onClickImg={this.onClickEleDiagram}
            onClickEnergyChart={this.onClickEnergyChart}
            onClickCheckStatistics={this.onClickCheckStatistics}
            onClickRunStatus={this.onClickRunStatus}
            onClickCheckInfo={this.onClickCheckInfo}
            handleCustomerStation={this.handleCustomerStation}
            photovoltaic={this.props.photovoltaic}
            energyStorage={this.props.energyStorage}
            chargingPile={this.props.chargingPile}
            lateLy30Charging={this.props.lateLy30Charging}
            fetchRealData={fetchRealData}
            isNormal={isNormal}
          />,
        );
        break;
      }
    }
    if (!this.popInfoWindow) {
      this.popInfoWindow = this.createInfoWindow(content, offset);
    }
    this.popInfoWindow.setContent(content);
    this.popInfoWindow.setAnchor(anchor);
    this.popInfoWindow.setOffset(offset);
    // 增加延迟
    setTimeout(() => {
      this.popInfoWindow.open(this.mapInstance, position);
    }, 100);
  };

  renderDom = (content = <div />) => {
    const dom = document.createElement('div');
    render(content, dom);
    return dom;
  };

  onClickMarker = record => {
    this.renderPopInfoWindow(record);
  };

  createMap = () => {
    if (this.mapInstance) {
      return this.mapInstance;
    }
    if (!mapNode) return;
    mapNode.style.width = `${this.props.width}px`;

    this.mapInstance = new AMap.Map(mapNode, {
      zoom: this.defaultZoom,
      zooms: [this.defaultZoom, 20],
      center: this.defaultCenter,
      resizeEnable: true,
      pitch: 45, // 地图俯仰角度，有效范围 0 度- 83 度
      rotation: 15,
      viewMode: '3D',
      mapStyle: 'amap://styles/852b41ec43aca7f9234571b282140fd2',
    });
    this.mapInstance.on('click', () => {
      this.clear();
    });
    this.setState({
      inited: true,
    });
    return this.mapInstance;
  };

  clear = () => {
    this.closeTableInfoWindow();
    this.closePopInfoWindow();
    this.props.dispatch({
      type: 'screen/handleSelectedPoint',
      payload: null,
    });
  };

  createInfoWindow = (content, offset = new AMap.Pixel(16, -45)) => {
    const infoWindow = new AMap.InfoWindow({
      isCustom: true, // 使用自定义窗体
      closeWhenClickMap: true,
      autoMove: false,
      anchor: 'bottom-left',
      content,
      offset,
    });
    return infoWindow;
  };

  render() {
    const { liveVideoShow, liveVideo, hasKey, scale, isNormal, peopleVideo } = this.props;
    return (
      <>
        <div className={styles.layer}>
          <Search
            // onChange={this.filterDataByType}
            scale={scale}
            isNormal={isNormal}
          />
          {this.mapInstance && (
            <Filter
              filter={this.filterData}
              mapInstance={this.mapInstance}
              resetScale={this.handleScale}
            />
          )}
          <PowerPayload />
          <div className={styles.bgLeftTop} />
          <div className={styles.bgLeftBottom} />
          <div className={styles.bgRightTop} />
          <div className={styles.bgRightBottom} />
        </div>
        <MapTools
          scale={scale}
          isNormal={isNormal}
          handleScale={this.handleScale}
          handleLocation={this.handleLocation}
        />
        <RealVideo />
        <EleDiagram />
        <RunStatus />
        <CheckInfo />
        {liveVideoShow && (
          <PlayerModal
            liveVideo={liveVideo}
            peopleVideo={peopleVideo}
            hasKey={hasKey}
            showLiveVideo={this.showLiveVideo}
            onLiveVideo={this.onLiveVideo}
          />
        )}
      </>
    );
  }
}

export default AMapCom;
