import _extends from "@babel/runtime/helpers/extends";
// Copyright 1999-2021. Plesk International GmbH. All rights reserved.
import React, { Fragment, isValidElement, cloneElement, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { CLS_PREFIX } from '../../constants';
import Overlay from '../Overlay';
import { useClosingConfirmation } from '../ClosingConfirmation';
import Header from './Header';
import ScrollDirection from './ScrollDirection';
import Form from '../Form';
import Heading from '../Heading';
import { isLikeText } from '../Translate';
import ScrollableElementFormContext from '../Form/ScrollableElementFormContext';
import DrawerProgress from './DrawerProgress';
const propTypes = {
  /**
   * Toggles visibility.
   * @since 0.0.65
   */
  isOpen: PropTypes.bool,

  /**
   * The title of the `Drawer`.
   * @since 0.0.65
   */
  title: PropTypes.node.isRequired,

  /**
   * The subtitle of the `Drawer`.
   * @since 0.0.65
   */
  subtitle: PropTypes.node,

  /**
   * Show the minimize button and the inactive close button.
   * @since 1.4.1
   */
  hideButton: PropTypes.bool,

  /**
   * Show back button in the header. If true the close button is not show.
   * @deprecated Not recommended to use. Use default close button instead.
   * @since 0.0.65
   */
  backButton: PropTypes.bool,

  /**
   * A slot for `Tabs` component.
   * @since 3.26.0
   */
  tabs: PropTypes.node,

  /**
   * Overlay placement.
   * @since 0.0.65
   */
  placement: PropTypes.oneOf(['left', 'right']),

  /**
   * Overlay size.
   * @since 0.0.65
   */
  size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']),

  /**
   * onClose handler.
   * @since 0.0.65
   */
  onClose: PropTypes.func,

  /**
   * Whether show or not a confirmation dialog on close.
   * @since 3.21.0
   */
  closingConfirmation: PropTypes.bool,

  /**
   * Wraps children into [Form](#!/Form) if not empty.
   * @since 0.0.66
   */
  form: PropTypes.oneOfType([PropTypes.object, PropTypes.element]),

  /**
   * Block with an image, placed at the side of the component
   * @since 3.25.0
   */
  sideBanner: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.element]),

  /**
   * Additional properties for the sideBanner
   * @since 3.25.0
   */
  sideBannerContainer: PropTypes.shape({
    /**
     * Values for css background property
     */
    background: PropTypes.string,

    /**
     * One of: center, flex-start, flex-end
     */
    align: PropTypes.oneOf(['center', 'flex-start', 'flex-end'])
  }),

  /**
   * Content of the `Drawer`.
   * @since 0.0.65
   */
  children: PropTypes.node,

  /**
   * Adds [Progress](#!/Progress) into footer.
   * @since 1.11.0
   */
  progress: PropTypes.shape({
    /**
     * A title for the progress.
     */
    title: PropTypes.string,

    /**
     * An array of [ProgressStep](#!/ProgressStep) props.
     */
    steps: PropTypes.arrayOf(PropTypes.shape({
      title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
      status: PropTypes.string,
      progress: PropTypes.number,
      icon: PropTypes.string
    })).isRequired,

    /**
     * An option that controls drawer closing ability.
     */
    cancelable: PropTypes.bool,

    /**
     * On overall status event handler.
     * @since 3.8.0
     */
    onStatusChange: PropTypes.func,

    /**
     * @ignore
     */
    onClose: PropTypes.func,

    /**
     * @ignore
     */
    onClosableChange: PropTypes.func
  }),

  /**
   * @ignore
   */
  className: PropTypes.string,

  /**
   * @ignore
   */
  baseClassName: PropTypes.string
};
const defaultProps = {
  isOpen: false,
  subtitle: '',
  backButton: undefined,
  hideButton: undefined,
  tabs: undefined,
  placement: 'left',
  size: 'md',
  onClose: null,
  closingConfirmation: undefined,
  form: null,
  sideBanner: undefined,
  sideBannerContainer: undefined,
  progress: null,
  children: null,
  className: null,
  baseClassName: `${CLS_PREFIX}drawer`
};
/**
 * `Drawer` component is used for working with properties of an object (or system) without leaving the context of the object.
 * The component is similar to `Dialog` but it is intended to work with more complex forms or lists.
 * @since 0.0.65
 */

const Drawer = ({
  baseClassName,
  className,
  children,
  title,
  subtitle,
  backButton,
  hideButton,
  tabs,
  onClose,
  form,
  progress,
  closingConfirmation,
  ...props
}) => {
  const scrollableRef = useRef();
  const [isClosable, setIsClosable] = useState(true);
  const {
    onCloseWithConfirmation,
    closingConfirmationDialog
  } = useClosingConfirmation({
    onClose,
    closingConfirmation
  });

  const takeApart = render => {
    if (progress) {
      progress.onClose = onCloseWithConfirmation;
      progress.onClosableChange = setIsClosable;

      const drawerProgressRender = ({
        content,
        footer
      }) => {
        return render({
          content: /*#__PURE__*/React.createElement("div", {
            className: `${baseClassName}__form`
          }, content),
          footer
        });
      };

      return /*#__PURE__*/React.createElement(DrawerProgress, _extends({
        render: drawerProgressRender
      }, progress));
    }

    if (form) {
      if ( /*#__PURE__*/isValidElement(form)) {
        return /*#__PURE__*/cloneElement(form, {
          className: classNames(`${baseClassName}__form`, form.props.className),
          cancelButton: form.props.cancelButton === false ? false : {
            onClick: onCloseWithConfirmation,
            ...form.props.cancelButton
          },
          render: ({
            renderForm,
            renderActionButtons
          }) => render({
            content: renderForm(),
            footer: renderActionButtons()
          })
        });
      }

      if (typeof form === 'object') {
        form.className = classNames(`${baseClassName}__form`, form.className);

        if (form.cancelButton !== false) {
          form.cancelButton = {
            onClick: onCloseWithConfirmation,
            ...form.cancelButton
          };
        }

        return /*#__PURE__*/React.createElement(Form, _extends({}, form, {
          render: ({
            renderForm,
            renderActionButtons
          }) => render({
            content: renderForm(),
            footer: renderActionButtons()
          })
        }), children);
      }
    }

    return render({
      content: /*#__PURE__*/React.createElement("div", {
        className: `${baseClassName}__inner-body`
      }, children)
    });
  };

  return /*#__PURE__*/React.createElement(Overlay, _extends({
    className: classNames(baseClassName, {
      [`${baseClassName}--form`]: form
    }, className),
    onClose: onCloseWithConfirmation,
    canCloseOnBackdropClick: true
  }, props), takeApart(({
    content,
    footer
  }) => /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(Header, {
    backButton: backButton,
    hideButton: typeof hideButton === 'boolean' ? hideButton : Boolean(progress && !isClosable),
    onClose: onCloseWithConfirmation,
    tabs: tabs
  }, isLikeText(title) ? /*#__PURE__*/React.createElement(Heading, {
    level: "2",
    className: `${baseClassName}__title`
  }, title) : /*#__PURE__*/React.createElement("div", {
    className: `${baseClassName}__title`
  }, title), subtitle && /*#__PURE__*/React.createElement("div", {
    className: `${baseClassName}__subtitle`
  }, subtitle)), /*#__PURE__*/React.createElement(ScrollDirection, null, ({
    handleScroll
  }) => /*#__PURE__*/React.createElement("div", {
    className: `${baseClassName}__body`,
    onScroll: handleScroll,
    ref: scrollableRef
  }, /*#__PURE__*/React.createElement(ScrollableElementFormContext.Provider, {
    value: scrollableRef.current
  }, content))), footer && /*#__PURE__*/React.createElement("footer", {
    className: `${baseClassName}__footer`
  }, /*#__PURE__*/React.createElement("div", {
    className: `${baseClassName}__footer-inner`
  }, footer)))), closingConfirmationDialog);
};

Drawer.propTypes = propTypes;
Drawer.defaultProps = defaultProps;
export default Drawer;