import React, { FC, ReactNode, useEffect, useState, useRef } from 'react';
import { useLayer, Arrow } from 'react-laag';
import { PopUpButton, PopUpBody } from './style';

type TPlacements =
  | 'bottom-start'
  | 'bottom-end'
  | 'bottom-center'
  | 'top-start'
  | 'top-center'
  | 'top-end';

export interface Props {
  body: ReactNode;
  active?: boolean;
  fullWidth?: boolean;
  padding?: string | number;
  borderRadius?: number;
  onOpenChange?: (val: boolean) => void;
  trigger?: boolean;
  placement?: TPlacements;
  arrow?: boolean;
  disableClickOutside?: boolean;
  disableAutoTrigger?: boolean;
  unsetWidth?: boolean;
  disableMaxHeight?: boolean;
  limitPlacements?: boolean;
  fullHeightContent?: boolean;
}

export const Popup: FC<Props> = ({
  children,
  body,
  onOpenChange,
  padding = 0.5,
  borderRadius = 5,
  fullWidth = false,
  trigger,
  placement = 'bottom-center',
  arrow = false,
  disableAutoTrigger = false,
  disableClickOutside = false,
  unsetWidth = false,
  disableMaxHeight = false,
  limitPlacements = false,
  fullHeightContent,
}) => {
  const [isOpen, setOpen] = useState(false);
  const ref = useRef(null);
  const [width, setWidth] = useState();

  useEffect(() => {
    if (fullWidth && ref.current) {
      // @ts-ignore: Object is possibly 'null'.
      setWidth(ref.current.offsetWidth);
    }
  }, [ref.current, fullWidth]);

  useEffect(() => {
    if (onOpenChange) {
      onOpenChange(isOpen);
    }
  }, [isOpen]);

  useEffect(() => {
    if (trigger !== undefined) {
      setOpen(trigger);
    }
  }, [trigger]);

  const { renderLayer, triggerProps, layerProps, arrowProps } = useLayer({
    isOpen,
    placement: placement,
    auto: true,
    possiblePlacements: [
      'bottom-start',
      'bottom-end',
      'bottom-center',
      'top-start',
      'top-center',
      'top-end',
    ],
    triggerOffset: 2,
    containerOffset: 13,
    arrowOffset: 8,
    onOutsideClick: () => {
      if (!disableClickOutside) {
        setOpen(false);
      }
    },
  });

  return (
    <>
      <div
        style={{ width: unsetWidth ? 'unset' : '100%', height: '100%' }}
        ref={ref}
      >
        <PopUpButton
          {...triggerProps}
          onClick={() => {
            if (!disableAutoTrigger) {
              setOpen(!isOpen);
            }
          }}
          style={{ height: fullHeightContent ? '100%' : undefined }}
        >
          {children}
        </PopUpButton>
      </div>
      {isOpen &&
        renderLayer(
          <div
            {...layerProps}
            style={{
              ...layerProps.style,
              zIndex: 100000,
              width: width,
              display: 'flex',
            }}
          >
            <PopUpBody
              borderRadius={borderRadius}
              padding={padding}
              disableMaxHeight={disableMaxHeight}
            >
              {body}
            </PopUpBody>
            {arrow && <Arrow {...arrowProps} />}
          </div>
        )}
    </>
  );
};
