import React, { FC, HTMLAttributes, Children, useState, useEffect, useRef, createContext, useMemo, startTransition } from "react";
import { getCN } from "../utils";
import "./ModalRoot.css";

export interface IModalRoot extends HTMLAttributes<HTMLDivElement> {
  activeModal: string;
  delay?: number;
  safe?: boolean;
  nav?: string;
  onClose?: () => void
};

class SaveContext {
  private value: Record<string, number> = {};

  constructor(value: Record<string, number>) {
    this.value = value;
  };

  public getvalue = (title: string) => this.value[title] || 0;
  public setValue = (title: string, value: number) => this.value[title] = value;
};

export const ScrollContext = createContext<SaveContext>(new SaveContext({}));

const ModalRoot: FC<IModalRoot> = ({
  activeModal,
  delay = 300,
  safe = true, //Безопасная зона
  children,
  onClose,
  ...restProps
}) => {
  const scrollContext = useRef<SaveContext>(new SaveContext({})).current;

  const [[back, active, animation, show], setNav] = useState(["", "", false, false]);

  const ModalRoots = useMemo(() => Children.toArray(children) as React.ReactElement[], [children]);

  const pageClose = ModalRoots.find((elem) => elem.props.id === back);
  const pageActive = ModalRoots.find((elem) => elem.props.id === active);

  useEffect(() => {
    handleCloseModal(active);
  }, [activeModal]);

  const handleCloseModal = (active: string, callback?: () => void) => {
    if (active !== activeModal) {
      setNav([active, activeModal, true, true]);

      const timer = setTimeout(() => {
        setNav([active, activeModal, false, false]);
      }, delay);
      if (callback) callback()
      return () => clearTimeout(timer);
    };
  }

  const handleClose = () => onClose && onClose()

  const hd = handleSwipe({
    maxTop: 0,
    onClose: () => handleClose()
  });


  return (
    <div
      style={{
        transition: `background ${delay / 1000}s`,
        ...hd.varTransformY,
        ...restProps.style
      }}
      {...restProps}
      {...hd.component}
      data-active={!!pageActive}
      className={getCN([
        "ModalRoot",
        safe && "ModalRoot__safe",
      ])}
    >

      <ScrollContext.Provider value={scrollContext}>
        {
          pageActive && (
            <div
              onClick={handleClose}
              style={{
                transform: animation ? show ? `translateY(100%)` : `translateY(0%)` : `translateY(${hd.transformY}px)`,
                transition: !hd.transformY ? `transform ${delay / 1000}s cubic-bezier(0.36,0.66,0.04,1)` : undefined
              }}
              key={active}
              className={getCN("ModalRoot__active")}
            >
              <div
                onClick={(e) => e.stopPropagation()}
                className={getCN("ModalRoot__active__in")}>
                {pageActive}
              </div>
            </div>
          )
        }
        {
          back && show && pageClose && (
            <div
              key={back}
              style={{
                transform: `translateY(100%)`,
                transition: `transform ${delay / 500}s cubic-bezier(0.36,0.66,0.04,1)`
              }}
              className={getCN("ModalRoot__close")}
            >
              {pageClose}
            </div>
          )
        }
      </ScrollContext.Provider>
    </div>
  );
};

export default ModalRoot;


type IHandleSwipe = {
  maxTop: number,
  bottomClose?: number,
  onClose?: () => void;
}
const handleSwipe = ({
  maxTop,
  bottomClose = 100,
  onClose
}: IHandleSwipe) => {
  const [transformY, setTransformY] = useState(0);
  const [touchStart, setTouchStart] = useState(0);


  const handleTouchStart = (e: React.TouchEvent<HTMLDivElement>) => {
    e.stopPropagation();
    setTouchStart(e.targetTouches[0].clientY);
  }
  const handleTouchMove = (e: React.TouchEvent<HTMLDivElement>) => {
    e.stopPropagation();
    const reTransform = e.targetTouches[0].clientY
    var px = reTransform - touchStart;
    if (px <= 0) {
      if (Math.abs(px) > maxTop) return;
    }
    setTransformY(px)
  }
  const handleTouchEnd = (e: React.TouchEvent<HTMLDivElement>) => {
    if (transformY >= bottomClose) {
      if (onClose) onClose();
    };
    setTransformY(0)
  }

  const varTransformY = {
    "--modal_root_transformY": `${transformY}px`
  } as React.CSSProperties;

  return {
    varTransformY,
    transformY,
    component: {
      onTouchStart: handleTouchStart,
      onTouchMove: handleTouchMove,
      onTouchEnd: handleTouchEnd,

      // onMouseDown: handleTouchEnd,
      // onMouseMove: handleTouchEnd,
      // onMouseUp: handleTouchEnd,
      // onMouseLeave: handleTouchEnd,
    }
  }
}