// @flow
import 'scss/component/_swipeable-drawer.scss';

// $FlowFixMe
import { Global } from '@emotion/react';
// $FlowFixMe
import { grey } from '@mui/material/colors';

import { HEADER_HEIGHT_MOBILE } from 'component/fileRenderFloating/view';
import { PRIMARY_PLAYER_WRAPPER_CLASS, PRIMARY_IMAGE_WRAPPER_CLASS } from 'page/file/view';
import { SwipeableDrawer as MUIDrawer } from '@mui/material';
import * as ICONS from 'constants/icons';
import * as React from 'react';
import Button from 'component/button';
import classnames from 'classnames';

const DRAWER_PULLER_HEIGHT = 42;

type Props = {
  children: Node,
  open: boolean,
  theme: string,
  mobilePlayerDimensions?: { height: number },
  title: any,
  hasSubtitle?: boolean,
  actions?: any,
  toggleDrawer: () => void,
};

export default function SwipeableDrawer(props: Props) {
  const { mobilePlayerDimensions, title, hasSubtitle, children, open, theme, actions, toggleDrawer } = props;

  const [coverHeight, setCoverHeight] = React.useState();

  const videoHeight = (mobilePlayerDimensions && mobilePlayerDimensions.height) || coverHeight || 0;

  const handleResize = React.useCallback(() => {
    const element =
      document.querySelector(`.${PRIMARY_IMAGE_WRAPPER_CLASS}`) ||
      document.querySelector(`.${PRIMARY_PLAYER_WRAPPER_CLASS}`);

    if (!element) return;

    const rect = element.getBoundingClientRect();
    setCoverHeight(rect.height);
  }, []);

  React.useEffect(() => {
    // Drawer will follow the cover image on resize, so it's always visible
    if (open && (!mobilePlayerDimensions || !mobilePlayerDimensions.height)) {
      handleResize();

      window.addEventListener('resize', handleResize);

      return () => window.removeEventListener('resize', handleResize);
    }
  }, [handleResize, mobilePlayerDimensions, open]);

  // Reset scroll position when opening: avoid broken position where
  // the drawer is lower than the video
  React.useEffect(() => {
    if (open) {
      const htmlEl = document.querySelector('html');
      if (htmlEl) htmlEl.scrollTop = 0;
    }
  }, [open]);

  return (
    <>
      <DrawerGlobalStyles open={open} videoHeight={videoHeight} />

      <MUIDrawer
        anchor="bottom"
        open={open}
        onClose={toggleDrawer}
        onOpen={toggleDrawer}
        hideBackdrop
        disableEnforceFocus
        disablePortal
        disableSwipeToOpen
        ModalProps={{ keepMounted: true }}
      >
        {open && (
          <div className="swipeable-drawer__header" style={{ top: -DRAWER_PULLER_HEIGHT }}>
            <Puller theme={theme} />
            <HeaderContents title={title} hasSubtitle={hasSubtitle} actions={actions} toggleDrawer={toggleDrawer} />
          </div>
        )}

        {children}
      </MUIDrawer>
    </>
  );
}

type GlobalStylesProps = {
  open?: boolean,
  videoHeight: number,
};

const DrawerGlobalStyles = (globalStylesProps: GlobalStylesProps) => {
  const { open, videoHeight } = globalStylesProps;

  return (
    <Global
      styles={{
        '.main-wrapper__inner--filepage': {
          overflow: open ? 'hidden' : 'unset',
          maxHeight: open ? '100vh' : 'unset',
        },
        '.main-wrapper .MuiDrawer-root': {
          top: `calc(${HEADER_HEIGHT_MOBILE}px + ${videoHeight}px) !important`,
        },
        '.main-wrapper .MuiDrawer-root > .MuiPaper-root': {
          overflow: 'visible',
          color: 'var(--color-text)',
          position: 'absolute',
          height: `calc(100% - ${DRAWER_PULLER_HEIGHT}px)`,
        },
      }}
    />
  );
};

type PullerProps = {
  theme: string,
};

const Puller = (pullerProps: PullerProps) => {
  const { theme } = pullerProps;

  return (
    <span className="swipeable-drawer__puller" style={{ backgroundColor: theme === 'light' ? grey[300] : grey[800] }} />
  );
};

type HeaderProps = {
  title: any,
  hasSubtitle?: boolean,
  actions?: any,
  toggleDrawer: () => void,
};

const HeaderContents = (headerProps: HeaderProps) => {
  const { title, hasSubtitle, actions, toggleDrawer } = headerProps;

  return (
    <div
      className={classnames('swipeable-drawer__header-content', {
        'swipeable-drawer__header--with-subtitle': hasSubtitle,
      })}
    >
      {title}

      <div className="swipeable-drawer__header-actions">
        {actions}

        <Button icon={ICONS.REMOVE} iconSize={16} onClick={toggleDrawer} />
      </div>
    </div>
  );
};

type ExpandButtonProps = {
  label: any,
  toggleDrawer: () => void,
};

export const DrawerExpandButton = (expandButtonProps: ExpandButtonProps) => {
  const { label, toggleDrawer } = expandButtonProps;

  return (
    <Button
      className="swipeable-drawer__expand-button"
      label={label}
      button="primary"
      icon={ICONS.CHAT}
      onClick={toggleDrawer}
    />
  );
};