import React, {Component, Fragment} from "react";
import {connect} from "react-redux";
import {Route, withRouter} from "react-router-dom";
import {ToastContainer} from "react-toastify";
import classnames from "classnames";
import {statics as contactListStatics} from "./ModalContactList";
import {isChannel} from "../utils/helpers";
import checkForPrivilege from "./../utils/privilege";
import "../../styles/utils/toaster.scss";

//strings
import strings from "../constants/localization";
import {CHAT_CALL_BOX_COMPACTED} from "../constants/callModes";
import {THREAD_ADMIN} from "../constants/privilege";
import {
  ROUTE_ADD_CONTACT,
  ROUTE_CONTACTS,
  ROUTE_CREATE_CHANNEL,
  ROUTE_CREATE_GROUP,
  ROUTE_JOIN_GROUP,
  ROUTE_SHARE,
  ROUTE_THREAD_INFO,
} from "../constants/routes";

//actions
import {contactGetList} from "../actions/contactActions";
import {
  chatClearCache, chatDestroy,
  chatNotification,
  chatNotificationClickHook,
  chatRetryHook,
  chatRouterLess,
  chatSetInstance,
  chatSignOutHook,
  chatSmallVersion, chatSupportMode, chatTypingHook
} from "../actions/chatActions";
import {
  threadCreateWithExistThread,
  threadCreateWithUser,
  threadGetList,
  threadParticipantList,
  threadShowing
} from "../actions/threadActions";
import {userGet} from "../actions/userActions";

//components
import Aside from "./Aside";
import Main from "./Main";
import CallBox from "./CallBox";
import CallBoxCompacted from "./CallBoxCompacted";
import LeftAside from "./LeftAside";
import Container from "../../../Talk-ui-kit/src/container";
import {Text} from "../../../Talk-ui-kit/src/typography";
import {ModalMedia} from "../../../Talk-ui-kit/src/modal";
import ModalContactListMenu from "./ModalContactListMenu";
import ModalAddContact from "./ModalAddContact";
import ModalThreadList from "./ModalThreadList";
import ModalCreateGroup from "./ModalCreateGroup";
import ModalThreadInfo from "./ModalThreadInfo";
import ModalImageCaption from "./ModalImageCaption";
import ModalPrompt from "./ModalPrompt";
import ModalShare from "./ModalShare";
import ModalJoin from "./ModalJoin";
import ModalParticipantList from "./ModalParticipantList";
import ModalExportMessages from "./ModalExportMessages";
import ModalDatePicker from "./ModalDatePicker";
import ModalCallErrorHandler from "./ModalCallErrorHandler";

//styling
import style from "../../styles/app/index.scss";

//statics

//functions

@connect(store => {
  return {
    chatInstance: store.chatInstance.chatSDK,
    chatRouterLess: store.chatRouterLess,
    user: store.user,
    thread: store.thread.thread,
    threadShowing: store.threadShowing,
    leftAsideShowing: store.threadLeftAsideShowing.isShowing,
    messageNew: store.messageNew,
    chatCallBoxShowing: store.chatCallBoxShowing
  };
}, null, null, {forwardRef: true})
class Index extends Component {
  constructor(props) {
    super(props);
    this.pickerRef = window.pickerRef = React.createRef();
    this.openThread = this.openThread.bind(this);
    this.modalDeleteMessagePromptRef = React.createRef();
    this.modalThreadListRef = React.createRef();
    this.modalMediaRef = React.createRef();
    this.modalImageCaptionRef = React.createRef();
    this.modalParticipantListRef = React.createRef();
    this.modalCallErrorRef = React.createRef();
    this.CallBoxRef = React.createRef();
    this.firstContactFetching = true;
    this.deletingDatabases = false;
  }

  componentDidUpdate(oldProps) {
    const {
      token,
      location,
      user: propsUser,
      chatInstance,
      dispatch,
      clearCache,
      thread,
      messageNew,
      onNewMessage,
      onReady
    } = this.props;
    const {
      token: oldToken,
      thread: oldThread,
      messageNew: oldMessageNew,
      user: oldUser,
      location: oldLocation
    } = oldProps;
    const {user, fetching: userFetching} = propsUser;

    //outside events handler
    if (onNewMessage) {
      if (!oldMessageNew && messageNew) {
        onNewMessage(messageNew);
      } else if (oldMessageNew) {
        if (oldMessageNew.id !== messageNew.id) {
          onNewMessage(messageNew, thread.id, thread);
        }
      }
    }
    if (onReady) {
      if (user.id !== oldUser.id) {
        onReady(user, chatInstance, this);
      }
    }
    //

    if (!thread.onTheFly) {
      if ((!oldThread.id && thread.id) || (oldThread.id !== thread.id)) {
        if (isChannel(thread)) {
          if (checkForPrivilege(thread, THREAD_ADMIN)) {
            dispatch(threadParticipantList(thread.id));
          }
        } else {
          dispatch(threadParticipantList(thread.id));
        }
      }
    }

    if (oldLocation.pathname !== location.pathname) {
      if (location.pathname === "/") {
        this.resetChat();
      }
    }

    if (oldToken) {
      if (oldToken !== token) {
        this.setToken(token);
      }
    }

    if (chatInstance) {
      if (this.firstContactFetching) {
        dispatch(contactGetList(contactListStatics.offset, contactListStatics.count));
        this.firstContactFetching = false;
      }
      if (clearCache && !this.deletingDatabases) {
        this.deletingDatabases = true;
        dispatch(chatClearCache());
      }
      if (!user.id) {
        if (!userFetching) {
          dispatch(userGet(chatInstance));
        }
      }
    }
  }

  resetChat() {
    const {dispatch} = this.props;
    dispatch(threadShowing(false));
    const closeModal = modal => modal.current.onClose();
    closeModal(this.modalDeleteMessagePromptRef);
    closeModal(this.modalThreadListRef);
    closeModal(this.modalImageCaptionRef);
    this.modalMediaRef.current.close();
  }

  componentDidMount() {
    const {
      small,
      supportMode,
      routerLess,
      dispatch,
      disableNotification,
      onNotificationClickHook,
      onRetryHook,
      onSignOutHook,
      onTypingHook
    } = this.props;
    dispatch(chatSetInstance(this.props));
    if (small || supportMode) {
      dispatch(chatSmallVersion(true))
    }
    if (supportMode) {
      dispatch(chatSupportMode(supportMode));
    }
    if (routerLess || supportMode) {
      dispatch(chatRouterLess(true))
    }
    if (disableNotification) {
      dispatch(chatNotification(false));
    }
    if (onNotificationClickHook) {
      dispatch(chatNotificationClickHook(onNotificationClickHook));
    }
    if (onRetryHook) {
      dispatch(chatRetryHook(onRetryHook));
    }
    if (onSignOutHook) {
      dispatch(chatSignOutHook(onSignOutHook));
    }
    if (onTypingHook) {
      dispatch(chatTypingHook(onTypingHook));
    }
    window.modalMediaRef = this.modalMediaRef.current;
  }

  componentWillUnmount() {
    const {dispatch, chatInstance} = this.props;
    dispatch(chatDestroy());
    chatInstance.logout();
  }

  setToken(token) {
    const {chatInstance} = this.props;
    if (chatInstance) {
      chatInstance.setToken(token);
    }
  }

  /*----outside api---*/
  openThread(thread) {
    const {dispatch} = this.props;
    if (thread instanceof Object) {
      dispatch(threadCreateWithExistThread(thread));
      return;
    }
    dispatch(threadCreateWithUser(thread, "TO_BE_USER_ID"));
  }

  refreshThreads() {
    const {dispatch} = this.props;
    dispatch(threadGetList(0, 50));
  }

  /*----outside api---*/

  render() {
    const {
      threadShowing,
      customClassName,
      leftAsideShowing,
      small,
      chatRouterLess,
      supportMode,
      chatCallBoxShowing
    } = this.props;
    const classNames = classnames({
      [customClassName]: customClassName,
      [style.Index]: true,
      [style["Index--small"]]: small || supportMode,
      [style["Index--isThreadShow"]]: threadShowing,
      [style["Index--isAsideLeftShow"]]: leftAsideShowing
    });


    const {showing: callBoxShowingType} = chatCallBoxShowing;
    const popups = (
      <Container>
        {supportMode ?
          <Fragment>
            <ModalPrompt smallVersion={small} ref={this.modalDeleteMessagePromptRef}/>
            <ModalMedia selector={`.${style.Index__MediaTrigger} a`}
                        ref={this.modalMediaRef}
                        lang="fa"
                        i18n={{fa: strings.modalMedia}}
                        backFocus={false}/>
            <ModalImageCaption smallVersion={small} ref={this.modalImageCaptionRef}/>
          </Fragment>
          :

          <Fragment>
            <ToastContainer
              enableMultiContainer
              containerId={"main-toaster"}
              position="top-right"
              autoClose={1000}
              hideProgressBar={false}
              newestOnTop={false}
              closeOnClick
              rtl
              pauseOnFocusLoss
              draggable
              pauseOnHover={false}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : [ROUTE_CREATE_GROUP, ROUTE_CREATE_CHANNEL]}
                   render={() => <ModalCreateGroup smallVersion={small}/>}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : ROUTE_CONTACTS}
                   render={() => <ModalContactListMenu smallVersion={small}/>}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : ROUTE_ADD_CONTACT}
                   render={() => <ModalAddContact smallVersion={small}/>}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : ROUTE_SHARE}
                   render={() => <ModalShare smallVersion={small}/>}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : ROUTE_JOIN_GROUP}
                   render={() => <ModalJoin smallVersion={small}/>}/>
            <Route exact={!chatRouterLess} path={chatRouterLess ? "" : ROUTE_THREAD_INFO}
                   render={() => <ModalThreadInfo smallVersion={small}/>}/>
            <ModalThreadList smallVersion={small} ref={this.modalThreadListRef}/>
            <ModalParticipantList smallVersion={small} ref={this.modalParticipantListRef}/>
            <ModalImageCaption smallVersion={small} ref={this.modalImageCaptionRef}/>
            <ModalExportMessages smallVersion={small} ref={this.modalImageCaptionRef}/>
            <ModalCallErrorHandler smallVersion={small} ref={this.modalCallErrorRef}/>
            <ModalMedia selector={`.${style.Index__MediaTrigger} a`}
                        ref={this.modalMediaRef}
                        lang="fa"
                        i18n={{fa: strings.modalMedia}}
                        backFocus={false}/>
            <ModalPrompt smallVersion={small} ref={this.modalDeleteMessagePromptRef}/>
          </Fragment>
        }
        <ModalDatePicker className={style.Index__DatePickerContainer}/>
      </Container>
    );

    return (
      <Container className={classNames}>
        {popups}
        {
          callBoxShowingType &&
          callBoxShowingType === CHAT_CALL_BOX_COMPACTED &&
          <CallBoxCompacted chatCallBoxShowing={chatCallBoxShowing} CallBoxRef={this.CallBoxRef}/>
        }
        <CallBox chatCallBoxShowing={chatCallBoxShowing} ref={this.CallBoxRef}/>
        {!supportMode &&
        <Container className={style.Index__Aside}>
          <Aside/>
        </Container>
        }
        <Container className={style.Index__Main}>
          <Main/>
        </Container>
        <Container className={style.Index__AsideLeft}>
          <LeftAside/>
        </Container>
      </Container>
    );
  }
}

export default withRouter(Index);


export function IndexModalMediaFragment({link, linkClassName, children, options, linkRef}) {
  const fixedOptions = options || {};

  return <Container className={style.Index__MediaTrigger} inline>
    <Text link={link}
          ref={linkRef}
          target={"_blank"}
          className={linkClassName}
          linkClearStyle
          data-options={JSON.stringify(fixedOptions)}>
      {children && children}
    </Text>

  </Container>
}