/**
 * @Author: ??
 * @Date: ??
 */
import React, { useCallback, useEffect, useImperativeHandle, useMemo, useState } from "react";
import { LayoutMapProps } from "./interface";
import { Layouts, Responsive as ResponsiveGridLayout } from "react-grid-layout";
import {
  breakpoints,
  cols,
  LayoutMapConfig,
  LayoutMedia,
  layouts,
  PLACE_ORDER_WIDTH,
  purePoints
} from "@components/LayoutMap/layoutMapConfig";
import { calcNewestNodeAndMedia, throttle } from "./utils";
import { clone, mapObjIndexed, pipe, values, reduce } from "ramda";
import { LocalStore } from "@utils/localStore";
import "./index.css";
import { FullScreenIcon } from "@icons/FullScreen";
import { IconCom } from "@icons/index";

/**
 * ### 引用方法
 * ```tsx
 * import { LayoutMap } from "@atomintl/exchange-ui";
 * ```
 */
export const LayoutMap: React.FC<LayoutMapProps> = props => {
  const { views, responsiveGridLayoutProps, layoutsCacheName } = props;
  const storageLayouts =
    layoutsCacheName && LocalStore.get(layoutsCacheName) ? JSON.parse(LocalStore.get(layoutsCacheName)) : undefined;
  const { innerWidth: initInnerWidth, currentMedia: initMedia } = calcNewestNodeAndMedia(
    purePoints,
    breakpoints as any
  );
  const [innerWidth, setInnerWidth] = useState<number>(initInnerWidth - PLACE_ORDER_WIDTH);
  const [currentMedia, setCurrentMedia] = useState<LayoutMedia>(initMedia);
  const [alternativeLayout, setAlternativeLayout] = useState<Layouts | undefined>();
  const [virtualViews, setVirtualViews] = useState<any>(views);
  const [isFull, setIsFull] = useState<boolean>(false);

  useEffect(() => {
    function handleWindowResize() {
      const { innerWidth, currentMedia } = calcNewestNodeAndMedia(purePoints, breakpoints as any);

      setInnerWidth(innerWidth - PLACE_ORDER_WIDTH);
      setCurrentMedia(currentMedia);
    }
    handleWindowResize();

    const throttledWindowResize = throttle(handleWindowResize, 5);
    window?.addEventListener("resize", throttledWindowResize);

    return () => window?.removeEventListener("resize", throttledWindowResize);
  }, []);

  let MetaViews = useMemo(() => {
    return pipe(
      mapObjIndexed((value, key) => ({ key, value })),
      values
    )(virtualViews);
  }, [virtualViews, alternativeLayout]);

  const onFullScreenTapped = useCallback(
    (e: React.MouseEvent<HTMLSpanElement, MouseEvent>, key: string) => {
      if (isFull) {
        setVirtualViews(views);
        setAlternativeLayout(undefined);
        setIsFull(false);
      } else {
        const dataGrid = LayoutMapConfig[currentMedia]?.dataGrid;
        const fullWidth = LayoutMapConfig[currentMedia]?.col;
        const fullHeight = reduce(
          (acc: number, value: any) => (value.i === "T" || value.i === "V" || value.i === "O" ? acc + value.h : acc),
          0,
          dataGrid
        );
        const lastDataGrid = [{ i: key, x: 0, y: 0, w: fullWidth, h: fullHeight }];
        const _layouts = clone(layouts);
        _layouts[currentMedia] = lastDataGrid;

        setVirtualViews({ [key]: virtualViews[key] });
        setAlternativeLayout(_layouts);
        setIsFull(true);
      }

      e.stopPropagation();
    },
    [isFull, views, currentMedia, virtualViews]
  );

  const onResizeHandle = useCallback(() => {
    if (isFull) {
      setVirtualViews(views);
      setAlternativeLayout(clone(layouts));
      setIsFull(false);
      return;
    }
    layoutsCacheName && LocalStore.remove(layoutsCacheName);
    const _layouts = clone(layouts);
    _layouts[currentMedia].push({ i: "INVISIBLE", x: 0, y: 0, w: 0, h: 0 });
    setAlternativeLayout(alternativeLayout ? undefined : _layouts);
  }, [isFull, views, layoutsCacheName, alternativeLayout]);

  useImperativeHandle(props.onRef, () => ({ onResizeHandle }));

  return (
    <ResponsiveGridLayout
      layouts={alternativeLayout || storageLayouts || layouts}
      breakpoints={breakpoints}
      cols={cols}
      width={innerWidth}
      margin={[1, 1]}
      containerPadding={[0, 0]}
      useCSSTransforms={true}
      isDraggable={true}
      isResizable={true}
      draggableHandle=".aax-draggableHandle"
      resizeHandles={["se"]}
      resizeHandle={<span className="react-resizable-handle react-resizable-handle-se"></span>}
      onLayoutChange={e => {
        if (!isFull && layoutsCacheName) {
          const _layouts = clone(layouts);
          _layouts[currentMedia] = e;
          LocalStore.set(layoutsCacheName, JSON.stringify(_layouts));
        }
      }}
      {...responsiveGridLayoutProps}
    >
      {MetaViews.map((_item, _index) => (
        <div key={_item.key} className={`overflow-hidden border-r border-t border-gray-4`}>
          {_item.key === "T" ? null : (
            <IconCom className={"fullScreen"} onClick={e => onFullScreenTapped(e, _item.key)}>
              <FullScreenIcon />
            </IconCom>
          )}
          {!React.isValidElement(_item.value)
            ? _item.value
            : React.cloneElement(_item.value, { ...(_item.value.props as object), onResizeHandle } as any)}
        </div>
      ))}
    </ResponsiveGridLayout>
  );
};

LayoutMap.defaultProps = {};

export type { LayoutMapProps };
export default LayoutMap;
