import React, {Component} from "react";
import {connect} from "react-redux";
import {withRouter} from "react-router-dom";
import {OnWindowFocusInOut, socketStatus} from "../utils/helpers";
import classnames from "classnames";
import Cookies from "js-cookie";

//strings
import strings from "../constants/localization";
import {SHOW_CALL_BUTTON} from "../constants/cookieKeys";
import {SHOW_CALL_BUTTONS_EVENT} from "../constants/callModes";

//actions
import {
  chatSearchShow,
} from "../actions/chatActions";

//components
import MakeGlobalCall from "./_component/MakeGlobalCall";
import AsideHeadMenu from "./AsideHeadMenu";
import Notification from "./Notification";
import Container from "../../../Talk-ui-kit/src/container";
import {Text} from "../../../Talk-ui-kit/src/typography";
import Loading, {LoadingBlinkDots} from "../../../Talk-ui-kit/src/loading";
import {MdMenu, MdClose, MdSearch} from "react-icons/md";

//styling
import style from "../../styles/app/AsidHead.scss";
import utilsStyle from "../../styles/utils/utils.scss";

//statics
const statics = {
  headMenuSize: 59
};

@connect(store => {
  return {
    chatState: store.chatState,
    chatInstance: store.chatInstance.chatSDK,
    chatRouterLess: store.chatRouterLess,
    chatSearchShowing: store.chatSearchShow,
    chatRetryHook: store.chatRetryHook,
    chatSignOutHook: store.chatSignOutHook,
    smallVersion: store.chatSmallVersion,
    user: store.user.user
  };
})
class AsideHead extends Component {

  constructor(props) {
    super(props);
    this.state = {
      isOpen: false,
      reConnecting: false,
      timeUntilReconnectTimer: null,
      showCallButton: Cookies.get(SHOW_CALL_BUTTON)
    };
    window.addEventListener(SHOW_CALL_BUTTONS_EVENT, e => {
      this.setState({
        showCallButton: true
      });
    });
    this.container = React.createRef();
    this.onCloseMenu = this.onCloseMenu.bind(this);
    this.onOpenMenu = this.onOpenMenu.bind(this);
    this.onRetryClick = this.onRetryClick.bind(this);
    this.onChatSearchToggle = this.onChatSearchToggle.bind(this);
    OnWindowFocusInOut(e => {
    }, e => {
      const {isDisconnected} = socketStatus(this.props.chatState);
      if (isDisconnected) {
        if (!this.state.reConnecting) {
          this.onRetryClick();
        }
      }
    })
  }

  componentDidUpdate(prevProps) {
    const {reConnecting, timeUntilReconnectTimer} = this.state;
    const {chatState} = this.props;
    if (reConnecting) {
      const {isConnected} = socketStatus(chatState);
      if (isConnected) {
        this.setState({
          reConnecting: false
        });
      }
    }
    if (chatState) {
      const {isDisconnected, timeUntilReconnect, isReconnecting} = socketStatus(chatState);
      const {
        isDisconnected: oldIsDisconnected,
        timeUntilReconnect: oldTimeUntilReconnect
      } = socketStatus(prevProps.chatState);

      if (isReconnecting) {
        clearInterval(this.timeRemainingToConnectIntervalId);
        if (timeUntilReconnectTimer) {
          this.setState({
            timeUntilReconnectTimer: null
          });
        }

      } else {
        if ((isDisconnected && !oldIsDisconnected) || (timeUntilReconnect !== oldTimeUntilReconnect)) {
          clearInterval(this.timeRemainingToConnectIntervalId);
          this.setState({
            timeUntilReconnectTimer: timeUntilReconnect / 1000
          });
          this.timeRemainingToConnectIntervalId = setInterval(() => {
            const {timeUntilReconnectTimer} = this.state;
            if (timeUntilReconnectTimer > 0) {
              this.setState({
                timeUntilReconnectTimer: timeUntilReconnectTimer - 1
              });
            } else {
              this.setState({
                timeUntilReconnectTimer: null
              });
              clearInterval(this.timeRemainingToConnectIntervalId);
            }
          }, 1000);
        }
      }
    }
  }

  onCloseMenu() {
    this.setState({
      isOpen: false
    });
  }

  onOpenMenu(e) {
    e.stopPropagation();
    this.setState({
      isOpen: true
    });
  }

  onRetryClick() {
    this.setState({
      reConnecting: true
    });
    clearTimeout(this.timeOutForTryButton);
    this.timeOutForTryButton = setTimeout(() => {
      const {isDisconnected} = socketStatus(this.props.chatState);
      if (isDisconnected) {
        this.setState({
          reConnecting: false
        });
      }
    }, 5000);
    const {chatRetryHook, chatInstance} = this.props;
    if (chatRetryHook) {
      chatRetryHook().then(token => {
        chatInstance.setToken(token);
        chatInstance.reconnect();
      });
    }
  }

  onChatSearchToggle() {
    const {chatSearchShowing, dispatch} = this.props;
    dispatch(chatSearchShow(!chatSearchShowing));
  }

  render() {
    const {chatRouterLess, chatSignOutHook, chatState, chatInstance, smallVersion, chatSearchShowing, user} = this.props;
    const {isOpen, reConnecting, timeUntilReconnectTimer, showCallButton, chatSettingsShow} = this.state;
    const {isReconnecting, isConnected, isDisconnected} = socketStatus(chatState);
    const iconSize = style.iconSizeLg.replace("px", "");
    const iconMargin = `${(statics.headMenuSize - iconSize) / 2}px`;
    const firstInit = !chatInstance;
    const classNames = classnames({
      [style.AsideHead]: true,
      [style["AsideHead--settingMode"]]: chatSettingsShow,
      [style["AsideHead--smallVersion"]]: smallVersion
    });
    return (
      <>
        <Container className={classNames} ref={this.container} relative>
          <Notification/>
          <MdMenu size={iconSize}
                  className={utilsStyle["u-clickable"]}
                  onClick={this.onOpenMenu} style={{color: style.colorWhite, margin: iconMargin}}/>
          <Container centerRight className={style.AsideHead__ConnectionHandlerContainer}>
            <Container inline>
              <Text size="lg" color="gray" light bold>
                {firstInit || reConnecting ? `${strings.chatState.connectingToChat}${reConnecting ? "" : "..."}` : isConnected ? strings.podchat : isReconnecting ? `${strings.chatState.reconnecting}...` : `${strings.chatState.networkDisconnected}...`}
              </Text>
            </Container>
            {isDisconnected && !reConnecting &&
            <Container inline onClick={this.onRetryClick}>
              <Text size="xs" color="gray" light linkStyle inline>{strings.tryAgain}</Text>
              {timeUntilReconnectTimer ?
                <Text size="xs" color="gray" light inline> ( {timeUntilReconnectTimer} )</Text> : ""}
            </Container>
            }
            {reConnecting &&
            <Container inline>
              <Loading><LoadingBlinkDots size="sm" invert/></Loading>
            </Container>
            }

          </Container>
          <Container centerLeft>
            {showCallButton &&
            <Container inline cursor="pointer" className={style.AsideHead__MakeCallContainer}>
              <MakeGlobalCall/>
            </Container>
            }
            <Container inline cursor="pointer" className={style.AsideHead__SearchContainer}
                       onClick={this.onChatSearchToggle}>
              {chatSearchShowing ?
                <MdClose size={style.iconSizeMd} color={style.colorWhite}/>
                :
                <MdSearch size={style.iconSizeMd} color={style.colorWhite}/>
              }
            </Container>
          </Container>
          <AsideHeadMenu user={user} chatSignOutHook={chatSignOutHook} isMenuOpen={isOpen} chatRouterLess={chatRouterLess} onCloseMenu={this.onCloseMenu}/>
        </Container>
      </>

    )
  }
}

export default withRouter(AsideHead);