import React, {
  CSSProperties,
  useState,
  useEffect,
  useCallback,
  forwardRef,
  useRef,
  useMemo,
} from 'react';
import classNames from '@pansy/classnames';
import { Button, Radio, message } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import Icon from '@sensoro/library/lib/components/icon-font';
import { Map, Controls, MapTheme } from '../map';
import { MouseTool, Markers } from '@sensoro/react-amap';
import { DeviceInfo } from './interface';
import Marker from './common/marker';
import Card from './common/card';
import styles from './index.less';

// 选择设备状态
// 1: 初始状态 2: 选择框选类型 3: 重新框选
type Status = 1 | 2 | 3;

interface SelectDeviceProps {
  // 设备唯一标识集合
  value?: string[];
  style?: CSSProperties;
  simpleMode?: boolean;
  // 指定设备中唯一标识 默认为 cid
  deviceKey?: string;
  devices?: DeviceInfo[];
  onChange?: (value: string[]) => void;
  onSelectDeviceClick?: () => void;
  readonly?: boolean;
  zoom?: number;
  center?: any;
}

let mouseTool: any = null;
let overlayer: any = null;

const SelectDevice = forwardRef((props: SelectDeviceProps, ref: any) => {
  const {
    style,
    devices = [],
    value = [],
    simpleMode,
    onSelectDeviceClick,
    onChange,
    deviceKey = 'cid',
    readonly,
    zoom,
    center,
  } = props;
  const [type, setType] = useState<string>('');
  const [status, setStatus] = useState<Status>(1);
  const [deviceList, setDeviceList] = useState<DeviceInfo[]>([]);
  const [selectDevices, setSelectDevices] = useState<DeviceInfo[]>([]);
  // 聚合实例
  const markersInstance = useRef<any>(null);
  // 地图实例
  const mapInstance = useRef<any>(null);
  const [mapIns, setMapIns] = useState<any>(null);
  const lock = useRef<boolean>(false);

  useEffect(() => {
    setTimeout(() => {
      if (
        !lock.current &&
        !simpleMode &&
        mapInstance.current &&
        markersInstance.current
      ) {
        mapInstance.current.setFitView(markersInstance.current);
        lock.current = true;
      }
    }, 200);
  }, [props.devices, props.simpleMode, markersInstance.current]);

  useEffect(() => {
    setDeviceList(
      devices.map(item => {
        return {
          ...item,
          position: {
            longitude: item.lng,
            latitude: item.lat,
          },
          selected: value.includes(item[deviceKey]),
        };
      }),
    );

    setSelectDevices(
      value
        .map(sn => {
          return devices.find(item => item[deviceKey] === sn) as any;
        })
        .filter(item => item),
    );

    if (!simpleMode && value.length === 0) {
      if (mapInstance.current && overlayer) {
        setStatus(1);
        mapInstance.current.remove([overlayer]);
      }
    }
  }, [props.devices, props.value, props.simpleMode]);

  const setSelectDevicesCallback = useCallback(
    (nextValue: DeviceInfo[] = []) => {
      setSelectDevices(nextValue);
      onChange?.(nextValue.map(item => item[deviceKey]));
    },
    [setSelectDevices],
  );

  const toolEvents = {
    created: (tool: any) => {
      mouseTool = tool;
    },
    draw({ obj }: any) {
      handleDrawEnd(obj);
    },
  };

  const markersEvents = {
    created: (markers: any) => {
      markersInstance.current = markers;
    },
  };

  const mapEvents = {
    created: (ins: any) => {
      setMapIns(ins);
      mapInstance.current = ins;
    },
  };

  /**
   * 绘制圆形
   */
  const handleDrawCircle = () => {
    if (mouseTool) {
      mouseTool.circle();
    }
  };

  /**
   * 绘制矩形
   */
  const handleDrawRectangle = () => {
    if (mouseTool) {
      mouseTool.rectangle();
    }
  };

  /**
   * 绘制多边形
   */
  const handleDrawPolygon = () => {
    if (mouseTool) {
      mouseTool.polygon();
    }
  };

  /**
   * 关闭绘图
   */
  const handleDrawClose = () => {
    if (mouseTool) {
      mouseTool.close();
    }
  };

  /**
   * 框选结束回调
   * @param obj
   */
  const handleDrawEnd = (obj: any) => {
    overlayer = obj;
    handleDrawClose();
    const devices: DeviceInfo[] = [];

    const newDevices = [...selectDevices];

    const ids: string[] = selectDevices.map(item => item[deviceKey]);

    let result = false;

    const newDeviceList = deviceList.map(item => {
      let selected = false;
      if (item.position && item.position.latitude && item.position.longitude) {
        if (
          obj.contains(
            new window.AMap.LngLat(
              item.position.longitude,
              item.position.latitude,
            ),
          )
        ) {
          devices.push(item);
          selected = true;
          result = true;
        }
      }

      if (ids.includes(item[deviceKey])) {
        selected = true;
      }

      return {
        ...item,
        selected,
      };
    });

    devices.forEach(item => {
      if (ids.indexOf(item[deviceKey]) === -1) {
        newDevices.push(item);
      }
    });

    setSelectDevicesCallback(newDevices);
    setDeviceList(newDeviceList);

    if (!result) {
      message.warning('未框选到任何设备');
      setStatus(2);
      setType('');
      mapInstance.current.remove([overlayer]);
    } else {
      setStatus(3);
    }
  };

  /**
   * 重新框选
   */
  const handleReframe = () => {
    setType('');
    setStatus(2);

    if (mapInstance && overlayer) {
      mapInstance.current.remove([overlayer]);
    }

    overlayer = null;
  };

  const handleReset = () => {
    const newDeviceList = deviceList.map(item => {
      return {
        ...item,
        selected: false,
      };
    });

    setDeviceList(newDeviceList);

    if (mapInstance.current && overlayer) {
      setStatus(1);
      mapInstance.current.remove([overlayer]);
    }
    setSelectDevicesCallback([]);
  };

  const handleDrawTypeChange = (value: string) => {
    setType(value);
    if (value === 'circle') {
      handleDrawCircle();
    }
    if (value === 'rectangle') {
      handleDrawRectangle();
    }
    if (value === 'polygon') {
      handleDrawPolygon();
    }
  };

  const handleDeviceRemove = (id: string) => {
    const newDeviceList = deviceList.map(item => {
      if (item[deviceKey] === id) {
        return {
          ...item,
          selected: false,
        };
      }

      return item;
    });

    const newSelectDevices = selectDevices.filter(
      item => item[deviceKey] !== id,
    );

    if (mapInstance.current && overlayer && newSelectDevices.length === 0) {
      setStatus(1);
      mapInstance.current.remove([overlayer]);
    }
    setDeviceList(newDeviceList);
    setSelectDevicesCallback(newSelectDevices);
  };

  const [mapThemeStatus, setMapThemeStatus] = useState(false);

  const Theme = useMemo(() => {
    return (
      <MapTheme
        small={true}
        noStyle={true}
        __map__={mapIns}
        defaultStatus={mapThemeStatus}
        onStatusChange={setMapThemeStatus}
      />
    );
  }, [mapIns, mapThemeStatus]);

  const mapProps = !zoom ? {} : { zoom, center };

  return (
    <div
      className={classNames(styles.main, {
        [`${styles.simple}`]: simpleMode,
      })}
      style={style}
      ref={ref}
    >
      <Map
        {...mapProps}
        events={mapEvents}
        features={mapThemeStatus ? [] : ['bg', 'point', 'road']}
      >
        {simpleMode && (
          <div className={classNames(styles.operation, styles.operationMin)}>
            {Theme}
            {!readonly && (
              <span onClick={onSelectDeviceClick}>
                <PlusOutlined />
                选择设备
              </span>
            )}
          </div>
        )}
        <Controls className={styles.controls} />
        {!simpleMode && status === 2 && (
          <>
            <div className={styles.operationLeft}>
              <span
                onClick={() => {
                  setStatus(1);
                }}
              >
                <Icon type="icon-close" />
                取消框选
              </span>
            </div>
            <div className={styles.operation}>
              <span
                className={classNames({
                  [styles.active]: type === 'circle',
                })}
                onClick={() => {
                  handleDrawTypeChange('circle');
                }}
              >
                <Icon type="icon-round-selection" />
                圆形
              </span>
              <span
                className={classNames({
                  [styles.active]: type === 'rectangle',
                })}
                onClick={() => {
                  handleDrawTypeChange('rectangle');
                }}
              >
                <Icon type="icon-square-selection" />
                矩形
              </span>
              <span
                className={classNames({
                  [styles.active]: type === 'polygon',
                })}
                onClick={() => {
                  handleDrawTypeChange('polygon');
                }}
              >
                <Icon type="icon-polygon-selected" />
                多边形
              </span>
            </div>
          </>
        )}
        {!simpleMode && (
          <div className={styles.operation}>
            {status === 1 && (
              <>
                {Theme}
                <span
                  onClick={() => {
                    setStatus(2);
                  }}
                >
                  <Icon type="icon-frame-selection" />
                  框选设备
                </span>
              </>
            )}
            {status === 3 && (
              <>
                {Theme}
                <span onClick={handleReframe}>
                  <Icon type="icon-reset" />
                  重新框选
                </span>
              </>
            )}
          </div>
        )}
        {!simpleMode && (
          <Card
            devices={selectDevices}
            deviceKey={deviceKey}
            onRemove={handleDeviceRemove}
            onReset={handleReset}
            className={styles.card}
          />
        )}

        <MouseTool events={toolEvents} />

        <Markers
          markers={deviceList || []}
          render={(data: DeviceInfo) => {
            return <Marker info={data} />;
          }}
          events={markersEvents}
          useCluster={{
            zoomOnClick: () => {},
            renderCluserMarker: ({ count, marker, markers }: any) => {
              const list: DeviceInfo[] = markers
                .map((item: any) => {
                  return item?.G?.extData;
                })
                .filter((item: DeviceInfo) => item?.selected);

              if (list.length) {
                marker.setContent(
                  `<div class="map-select-device-markers"><span class="ant-badge ant-badge-not-a-wrapper"><sup class="ant-badge-count">${list.length}</sup></span>${count}</div>`,
                );
              } else {
                marker.setContent(
                  `<div class="map-select-device-markers">${count}</div>`,
                );
              }
            },
          }}
        />
      </Map>
    </div>
  );
});

SelectDevice.defaultProps = {
  simpleMode: true,
  deviceKey: 'cid',
  value: [],
  devices: [],
};

export default SelectDevice;
