import React, { MouseEventHandler } from 'react';
import clsx from 'clsx';
import { AccountSwitcher } from 'app/components/accounts';

import styles from './loggedInPanel.scss';

export default class LoggedInPanel extends React.Component<
  {
    username: string;
  },
  {
    isAccountSwitcherActive: boolean;
  }
> {
  state = {
    isAccountSwitcherActive: false,
  };

  _isMounted: boolean = false;
  el: HTMLElement | null;

  componentDidMount() {
    if (window.document) {
      // @ts-ignore
      window.document.addEventListener('click', this.onBodyClick);
    }

    this._isMounted = true;
  }

  componentWillUnmount() {
    if (window.document) {
      // @ts-ignore
      window.document.removeEventListener('click', this.onBodyClick);
    }

    this._isMounted = false;
  }

  render() {
    const { username } = this.props;
    const { isAccountSwitcherActive } = this.state;

    return (
      <div ref={(el) => (this.el = el)} className={clsx(styles.loggedInPanel)}>
        <div
          className={clsx(styles.activeAccount, {
            [styles.activeAccountExpanded]: isAccountSwitcherActive,
          })}
        >
          <button
            className={styles.activeAccountButton}
            onClick={this.onExpandAccountSwitcher}
          >
            <span className={styles.userIcon} />
            <span className={styles.userName}>{username}</span>
            <span className={styles.expandIcon} />
          </button>

          <div className={clsx(styles.accountSwitcherContainer)}>
            <AccountSwitcher
              skin="light"
              onAfterAction={this.onToggleAccountSwitcher}
            />
          </div>
        </div>
      </div>
    );
  }

  toggleAccountSwitcher = () =>
    this._isMounted &&
    this.setState({
      isAccountSwitcherActive: !this.state.isAccountSwitcherActive,
    });

  onToggleAccountSwitcher = () => {
    this.toggleAccountSwitcher();
  };

  onExpandAccountSwitcher = (event: React.MouseEvent<HTMLButtonElement>) => {
    event.preventDefault();

    this.toggleAccountSwitcher();
  };

  onBodyClick = createOnOutsideComponentClickHandler(
    () => this.el,
    () => this.state.isAccountSwitcherActive && this._isMounted,
    () => this.toggleAccountSwitcher(),
  );
}

/**
 * Creates an event handling function to handle clicks outside the component
 *
 * The handler will check if current click was outside container el and if so
 * and component isActive, it will call the callback
 *
 * @param  {Function} getEl - the function, that returns reference to container el
 * @param  {Function} isActive - whether the component is active and callback may be called
 * @param  {Function} callback - the callback to call, when there was a click outside el
 *
 * @returns {Function}
 */
function createOnOutsideComponentClickHandler(
  getEl: () => HTMLElement | null,
  isActive: () => boolean,
  callback: () => void,
): MouseEventHandler {
  // TODO: we have the same logic in LangMenu
  // Probably we should decouple this into some helper function
  // TODO: the name of function may be better...
  return (event) => {
    const el = getEl();

    if (isActive() && el) {
      if (!el.contains(event.target as HTMLElement) && el !== event.target) {
        event.preventDefault();

        // add a small delay for the case someone have alredy called toggle
        setTimeout(() => isActive() && callback(), 0);
      }
    }
  };
}
