/**
 * TEAM: frontend_infra
 * @flow
 */
import * as React from "react";
import {StyleSheet, css} from "aphrodite";

import {CSSTransition} from "react-transition-group";
// TODO: Fix this eslint issue on next edit. This is an autogenerated comment.
// eslint-disable-next-line flexport/no-legacy-dependencies
import deprecatedZIndices from "latitude/tools/deprecatedZIndices";
import IconButton from "./button/IconButton";
import Text from "./Text";
import StackingContext from "./StackingContext";

import Portal from "./Portal";
import colors from "./colors";

export const DRAWER_WIDTHS = {
  xs: 300,
  s: 400,
  m: 500,
  l: 600,
};

const TRANSITION_DELAY = 320;
const WORKSPACE_DEFAULT_NAV_HEIGHT = 56;

type Props = {|
  +children?: React.Node,
  +title: string,
  +navOffset?: number,
  +isOpen: boolean,
  +onClose: () => void,
  +width?: $Keys<typeof DRAWER_WIDTHS>,
|};

/**
 * @category Layout
 * @short Drawers slide in from the side of the viewport and allow for any custom content
 * @brandStatus V3
 * @status Beta
 */
function Drawer({
  children,
  title,
  navOffset = WORKSPACE_DEFAULT_NAV_HEIGHT,
  isOpen,
  onClose,
  width = "s",
}: Props): React.Node {
  const styles = getStyles(width);
  const {isDeprecatedZIndexEnabled} = React.useContext(StackingContext);

  return (
    <Portal>
      <div
        className={css(styles.drawerWrapper, styles.transitionGroup)}
        style={{top: navOffset}}
      >
        <CSSTransition
          in={isOpen}
          classNames={{
            enter: css(styles.drawerEnter),
            enterActive: css(styles.drawerEnterActive),
            exit: css(styles.drawerExit),
            exitActive: css(styles.drawerExitActive),
          }}
          timeout={{
            enter: TRANSITION_DELAY,
            exit: TRANSITION_DELAY,
          }}
          mountOnEnter={true}
          unmountOnExit={true}
        >
          <div
            className={css(
              styles.container,
              isDeprecatedZIndexEnabled && styles.containerZIndex
            )}
            style={{
              height: `calc(100vh - ${navOffset}px)`,
            }}
          >
            <div className={css(styles.header)}>
              <Text scale="headline" weight="bold">
                {title}
              </Text>
              <IconButton
                iconName="cancel"
                intent="none"
                kind="hollow"
                type="button"
                onClick={onClose}
              />
            </div>
            <div className={css(styles.body)}>{children}</div>
          </div>
        </CSSTransition>
      </div>
    </Portal>
  );
}

function getStyles(width: $Keys<typeof DRAWER_WIDTHS>) {
  return StyleSheet.create({
    drawerWrapper: {
      position: "absolute",
      right: 0,
      bottom: 0,
    },
    container: {
      width: `${DRAWER_WIDTHS[width]}px`,
      position: "fixed",
      backgroundColor: colors.grey10,
      boxShadow: "0 0 20px rgba(57, 65, 77, 0.15)",
      pointerEvents: "all",
      display: "flex",
      flexDirection: "column",
    },
    containerZIndex: {
      zIndex: deprecatedZIndices.zIndexPageOverlay.zIndex,
    },
    header: {
      display: "flex",
      justifyContent: "space-between",
      padding: "32px",
    },
    body: {
      flex: 1,
      overflowY: "auto",
    },
    transitionGroup: {
      display: "flex",
      justifyContent: "flex-end",
    },
    drawerEnter: {
      right: `-${DRAWER_WIDTHS[width]}px`,
    },
    drawerEnterActive: {
      right: "0px",
      transition: `right ${TRANSITION_DELAY}ms cubic-bezier(0.645, 0.045, 0.355, 1.000)`,
    },
    drawerExit: {
      right: "0px",
    },
    drawerExitActive: {
      right: `-${DRAWER_WIDTHS[width]}px`,
      transition: `right ${TRANSITION_DELAY}ms cubic-bezier(0.645, 0.045, 0.355, 1.000)`,
    },
  });
}

export default Drawer;
