function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

/*
Copyright (c) 2018-2020 Uber Technologies, Inc.

This source code is licensed under the MIT license found in the
LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import { getOverrides, mergeOverrides } from '../helpers/overrides.js';
import DeleteIcon from '../icon/delete.js';
import { Body as StyledBody, CloseIconSvg as StyledCloseIcon, InnerContainer as StyledInnerContainer } from './styled-components.js';
import { KIND, TYPE } from './constants.js';
import { LocaleContext } from '../locale/index.js';

class Toast extends React.Component {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "autoHideTimeout", void 0);

    _defineProperty(this, "animateInTimer", void 0);

    _defineProperty(this, "animateOutCompleteTimer", void 0);

    _defineProperty(this, "state", {
      isVisible: false,
      isRendered: true
    });

    _defineProperty(this, "animateIn", () => {
      // Defer to next event loop
      this.animateInTimer = setTimeout(() => {
        this.setState({
          isVisible: true
        });
      }, 0);
    });

    _defineProperty(this, "animateOut", (callback = () => {}) => {
      this.setState({
        isVisible: false
      }); // Remove the toast from the DOM after animation finishes

      this.animateOutCompleteTimer = setTimeout(() => {
        this.setState({
          isRendered: false
        });
        callback();
      }, 600);
    });

    _defineProperty(this, "dismiss", () => {
      this.animateOut(this.props.onClose);
    });

    _defineProperty(this, "onFocus", e => {
      this.clearTimeout();
      typeof this.props.onFocus === 'function' && this.props.onFocus(e);
    });

    _defineProperty(this, "onMouseEnter", e => {
      this.clearTimeout();
      typeof this.props.onMouseEnter === 'function' && this.props.onMouseEnter(e);
    });

    _defineProperty(this, "onBlur", e => {
      this.startTimeout();
      typeof this.props.onBlur === 'function' && this.props.onBlur(e);
    });

    _defineProperty(this, "onMouseLeave", e => {
      this.startTimeout();
      typeof this.props.onMouseLeave === 'function' && this.props.onMouseLeave(e);
    });
  }

  componentDidMount() {
    this.animateIn();
    this.startTimeout();
  }

  componentDidUpdate(prevProps) {
    if (this.props.autoHideDuration !== prevProps.autoHideDuration || this.props.__updated !== prevProps.__updated) {
      this.startTimeout();
    }
  }

  componentWillUnmount() {
    this.clearTimeout();
  }

  startTimeout() {
    if (this.props.autoHideDuration) {
      if (this.autoHideTimeout) {
        clearTimeout(this.autoHideTimeout);
      }

      this.autoHideTimeout = setTimeout(this.dismiss, this.props.autoHideDuration);
    }
  }

  clearTimeout() {
    [this.autoHideTimeout, this.animateInTimer, this.animateOutCompleteTimer].forEach(timerId => {
      if (timerId) {
        clearTimeout(timerId);
      }
    });
  }

  getSharedProps() {
    const {
      kind,
      notificationType,
      closeable
    } = this.props;
    const {
      isRendered,
      isVisible
    } = this.state;
    return {
      $kind: kind,
      $type: notificationType,
      $closeable: closeable,
      $isRendered: isRendered,
      $isVisible: isVisible
    };
  }

  render() {
    const {
      children,
      closeable
    } = this.props;
    const {
      isRendered
    } = this.state;
    const {
      Body: BodyOverride,
      CloseIcon: CloseIconOverride,
      InnerContainer: InnerContainerOverride
    } = this.props.overrides;
    const [Body, bodyProps] = getOverrides(BodyOverride, StyledBody);
    const [InnerContainer, innerContainerProps] = getOverrides(InnerContainerOverride, StyledInnerContainer);
    const [CloseIcon, closeIconProps] = getOverrides(CloseIconOverride, StyledCloseIcon);
    const closeIconOverrides = mergeOverrides({
      Svg: CloseIcon
    }, // $FlowFixMe
    {
      Svg: CloseIconOverride
    });
    const sharedProps = this.getSharedProps();

    if (!isRendered) {
      return null;
    }

    return React.createElement(LocaleContext.Consumer, null, locale => React.createElement(Body, _extends({
      role: "alert",
      "data-baseweb": this.props['data-baseweb'] || 'toast',
      tabIndex: -1
    }, sharedProps, bodyProps, {
      // the properties below have to go after overrides
      onBlur: this.onBlur,
      onFocus: this.onFocus,
      onMouseEnter: this.onMouseEnter,
      onMouseLeave: this.onMouseLeave
    }), React.createElement(InnerContainer, _extends({}, sharedProps, innerContainerProps), typeof children === 'function' ? children({
      dismiss: this.dismiss
    }) : children), closeable ? React.createElement(DeleteIcon, _extends({
      role: "button",
      tabIndex: 0,
      onClick: this.dismiss,
      onKeyPress: event => {
        if (event.key === 'Enter') {
          this.dismiss();
        }
      },
      title: locale.toast.close
    }, sharedProps, closeIconProps, {
      overrides: closeIconOverrides
    })) : null));
  }

}

_defineProperty(Toast, "defaultProps", {
  autoHideDuration: 0,
  closeable: true,
  kind: KIND.info,
  notificationType: TYPE.toast,
  // Do we need a separate handler for
  // when a notification dismisses automatically
  onClose: () => {},
  onBlur: () => {},
  onFocus: () => {},
  onMouseEnter: () => {},
  onMouseLeave: () => {},
  overrides: {}
});

export default Toast;