/*by Артур Франк https://vk.com/gmelum*/
import React, { FC, HTMLAttributes, Children, useState, useEffect, useRef, createContext, useMemo, startTransition } from "react";
import { getCN} from "../utils";
import "./View.css";

interface IView extends HTMLAttributes<HTMLDivElement> {
  activePanel: string;
  delay?: number;
  safe?: boolean;
  nav?: string;
};

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 View: FC<IView> = ({
  activePanel,
  delay = 400,
  safe = true, //Безопасная зона
  children,
  ...restProps
}) => {
  const scrollContext = useRef<SaveContext>(new SaveContext({})).current;

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

  const views = useMemo(() => Children.toArray(children) as React.ReactElement[], [children]);
  const viewsNav = useMemo(() => views.map((i) => i.props.id), [children]);

  const pageBack = views.find((elem) => elem.props.id === back);
  const pageActive = views.find((elem) => elem.props.id === active);

  const indexBack = viewsNav.indexOf(back);
  const indexActive = viewsNav.indexOf(activePanel);

  const isBack = indexActive < indexBack;
  const isNext = indexActive > indexBack;

  useEffect(() => {
    if (active !== activePanel) {
      setNav([active, activePanel, true, true]);

      const timer = window.setTimeout(() => {
        setNav([active, activePanel, true, false]);
      }, delay);

      return () => window.clearTimeout(timer);
    };
  }, [activePanel]);
  return (
    <div
      {...restProps}
      className={getCN([
        "View",
        safe && "View__safe",
        isBack && animation && show && "View__down",
        isNext && animation && show && "View__next",
        (!animation || !show) && "View__visible"
      ])}
    >
      <ScrollContext.Provider value={scrollContext}>
        {
          pageActive && (
            <div
              key={active}
              className={getCN("View__active")}
            >
              {pageActive}
            </div>
          )
        }
        {
          show && back && pageBack && (
            <div
              key={back}
              className={getCN("View__back")}
            >
              {pageBack}
            </div>
          )
        }
      </ScrollContext.Provider>
    </div>
  );
};

export default View;
