import { clsx } from 'clsx';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import { CSSTransition } from 'react-transition-group';

import { Position } from '../common';

export const EXIT_ANIMATION = 350;

export interface SlidingPanelProps extends Pick<
  React.ComponentPropsWithRef<'div'>,
  'ref' | 'className' | 'children'
> {
  position?: `${Position.TOP | Position.RIGHT | Position.BOTTOM | Position.LEFT}`;
  open: boolean;
  showSlidingPanelBorder?: boolean;
  slidingPanelPositionFixed?: boolean;
  testId?: string;
}

const SlidingPanel = forwardRef(
  (
    {
      position = 'left',
      open,
      showSlidingPanelBorder,
      slidingPanelPositionFixed,
      className,
      children,
      testId,
      ...rest
    }: Omit<SlidingPanelProps, 'ref'>,
    reference: React.ForwardedRef<HTMLDivElement | null>,
  ) => {
    const localReference = useRef<HTMLDivElement>(null as never);
    useImperativeHandle(reference, () => localReference.current, []);

    return (
      <CSSTransition
        {...rest}
        key={`sliding-panel--open-${position}`}
        nodeRef={localReference}
        in={open}
        // Wait for animation to finish before unmount.
        timeout={{ enter: 0, exit: EXIT_ANIMATION }}
        classNames="sliding-panel"
        appear
        unmountOnExit
      >
        <div
          ref={localReference}
          data-testid={testId}
          className={clsx(
            'sliding-panel',
            `sliding-panel--open-${position}`,
            showSlidingPanelBorder && `sliding-panel--border-${position}`,
            slidingPanelPositionFixed && 'sliding-panel--fixed',
            className,
          )}
        >
          {children}
        </div>
      </CSSTransition>
    );
  },
);

export default SlidingPanel;
