import { observer } from 'mobx-react';
import React, { useEffect } from 'react';
import { ButtonClose } from '../buttons/ButtonClose';
import { useApphouse } from '../../context/useApphouse';
import { css } from 'glamor';
import { merge } from '../../utils/obj/merge';
import { mergeStyles } from '../../styles/mergeStyles';
import {
  getSelfStylesForPosition,
  getStylesForPosition
} from '../../utils/styles/getStylesForPosition';
import { getGutterStyles } from '../../styles/getGutterStyles';
import { PopupProps, PopupStyles } from './Popup.interface';
import { Elevation } from '../../styles/defaults/elevation.styles';
import { fadeIn } from '../../styles/defaults/animations';

export interface PopupContainerProps extends PopupProps {
  /**
   * The maximum height of the popup
   */
  maxHeight?: string;
}
/**
 * Popup component
 *
 * Usage:
 * `npm install apphouse`
 *
 * `import { Popup } from 'apphouse'`
 *
 * Toggle the popup to open in any component:
 *
 * ```tsx
 * const {openPopup} = useApphouse();
 * <Button onClick={() => { openPopup(popup) }}>Toggle Popup</Button>
 * ```
 */
export const PopupContainer: React.FC<PopupContainerProps> = observer(
  (props) => {
    const {
      children,
      closeOnClickOutside = false,
      disableClosing = false,
      fullscreen = false,
      id,
      styleOverwrites,
      allowOverlayPassThrough = false,
      width,
      showCloseButton = false,
      stickyFooter = false,
      position = 'center',
      gutters = 0,
      maxHeight: _maxHeight
    } = props;
    const {
      app,
      closePopup,
      theme: { tokens, styles, colors }
    } = useApphouse();

    const { windowHeight, windowWidth } = app.layout;
    const popupWrapperRef = React.useRef<HTMLDivElement>(null);
    const popupRef = React.useRef<HTMLDivElement>(null);
    const maxHeight = _maxHeight || windowHeight;

    useEffect(() => {
      if (popupRef.current) {
        popupRef.current.focus();
      }
    });

    const popupStyles = {
      overlay: { ...styles.layout.overlay },
      popup: {
        alignItems: 'center',
        animation: `${fadeIn} 0.3s ease-in-out`,
        borderRadius: tokens.radius.m,
        boxSizing: 'border-box',
        display: 'flex',
        justifyContent: 'center'
      },
      container: {
        backgroundColor: colors.surface,
        border: `1px solid ${colors.onSurface}`,
        borderRadius: tokens.radius.default,
        boxSizing: 'border-box',
        display: 'grid',
        fontFamily: tokens.fontFamily.text,
        outline: 'none',
        overflow: 'hidden',
        ...Elevation.depth5,
        position: 'relative'
      }
    };

    const _windowHeight = `${windowHeight}px`;
    const localStyles: PopupStyles = merge(
      popupStyles,
      {
        // no overlay if needed if fullscreen
        overlay: fullscreen ? {} : getStylesForPosition(position),
        popup: fullscreen
          ? {
              height: _windowHeight
            }
          : { maxHeight: `${maxHeight}px` },
        container: fullscreen
          ? {
              width: '100%',
              height: _windowHeight,
              position: 'fixed',
              maxHeight: _windowHeight,
              top: 0,
              left: 0,
              margin: 0
            }
          : {
              width: `${windowWidth - 100}px`,
              maxHeight: `${windowHeight - 100}px`
            }
      },
      // If the popup has sticky footer, we don't want the container to scroll
      // and the content will scroll instead
      stickyFooter
        ? {
            container: { overflowY: 'none' }
          }
        : {}
    );

    let overlayStyles = merge(
      {},
      localStyles.overlay,
      styleOverwrites?.overlay
    );
    if (allowOverlayPassThrough) {
      // add styles to make the overlay transparent and pass through clicks
      overlayStyles = mergeStyles(overlayStyles, {
        backgroundColor: 'transparent',
        pointerEvents: 'none',
        ...getStylesForPosition(position)
      });
    }

    // Styles for the popup
    const popupContainerStyles = merge(
      {},
      // the default styles for the container
      localStyles.container,
      // the styles for the position of the popup
      getSelfStylesForPosition(position),
      // the styles for the width
      width ? { width } : {},
      // the overwrites for the container
      styleOverwrites?.container || {},
      // the styles for the gutter
      getGutterStyles(gutters)
    );

    return (
      <div
        ref={popupWrapperRef}
        onClick={(e) => {
          if (!allowOverlayPassThrough) {
            if (disableClosing) {
              return;
            }
            closeOnClickOutside && closePopup(id);
          } else {
            // overlay is supposed to be transparent and ignored
            // so clicks should pass through
            e.stopPropagation();
          }
        }}
        data-xray="PopupContainer"
        data-style="PopupContainer.overlay"
        {...css(overlayStyles)}
      >
        <div
          id={id}
          onClick={(e) => {
            // This will avoid the popup to close when clicking inside the popup
            e.stopPropagation();
            e.preventDefault();
            if (disableClosing) {
              return;
            }
          }}
          data-xray="Popup"
          data-style="PopupContainer.popup"
          {...css(localStyles.popup, styleOverwrites?.popup, {
            pointerEvents: 'all'
          })}
        >
          <div
            data-xray="PopupContainer"
            ref={popupRef}
            tabIndex={0}
            data-style="PopupContainer.container"
            {...css(popupContainerStyles)}
          >
            {showCloseButton && (
              <div
                {...css({ position: 'absolute', right: 0, top: 0 })}
                data-style="PopupContainer.closeButtonWrapper"
              >
                <ButtonClose
                  onClick={() => {
                    if (disableClosing) {
                      return;
                    }
                    app.popups.clear();
                  }}
                  data-style="PopupContainer.closeButton"
                  styleOverwrites={localStyles.closeButton}
                />
              </div>
            )}
            {children}
          </div>
        </div>
      </div>
    );
  }
);
