import React, {Component, Fragment} from "react";
import {connect} from "react-redux";
import classnames from "classnames";
import Draggable from "react-draggable";
import {isGroup, isRecording, isScreenShare, mobileCheck} from "../utils/helpers";

//strings
import {
  CHAT_CALL_BOX_COMPACTED,
  CHAT_CALL_BOX_FULL_SCREEN,
  CHAT_CALL_BOX_NORMAL,
  CHAT_CALL_STATUS_INCOMING,
  CHAT_CALL_STATUS_OUTGOING,
  CHAT_CALL_STATUS_STARTED,
  DROPPING_INCOMING_TIME_OUT,
  DROPPING_OUTGOING_TIME_OUT
} from "../constants/callModes";

//actions
import {
  chatCallBoxShowing as chatCallBoxShowingAction,
  chatRejectCall
} from "../actions/chatActions";

//components
import CallBoxHead from "./CallBoxHead";
import CallBoxSceneGroup from "./CallBoxSceneGroup";
import CallBoxScenePerson from "./CallBoxScenePerson";
import CallBoxControlSet from "./CallBoxControlSet";
import CallBoxRecording from "./CallBoxRecording";
import Container from "../../../Talk-ui-kit/src/container";

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

//statics

//functions

import ringtoneSound from "../constants/ringtone.mp3";
import callingTone from "../constants/callingTone.mp3";
import {CHAT_SETTING_KEYS} from "../constants/chatSettings";


@connect(store => {
  return {
    callChatSettings: store.chatSettings[CHAT_SETTING_KEYS.CALL.MAIN],
    chatCallStatus: store.chatCallStatus,
    threadObject: store.thread
  }
}, null, null, {forwardRef: true})
export default class CallBox extends Component {

  constructor(props) {
    super(props);
    this.onCallBoxClick = this.onCallBoxClick.bind(this);
    //create notification audio tag
    this.playRingtone = this.playRingtone.bind(this);
    this.stopRingtone = this.stopRingtone.bind(this);
    this.hideOrShowControls = this.hideOrShowControls.bind(this);
    this.refo = React.createRef();
    this.interValId = null;
    this.ringtone = new Audio(ringtoneSound);
    this.ringtone.loop = true;
    this.ringtone.muted = true;

    this.callingTone = new Audio(callingTone);
    this.callingTone.loop = true;
    this.callingTone.muted = true;
    this.state = {
      showControl: true
    };
  }

  setTimeoutForDropping(type, timeout) {
    const {dispatch} = this.props;
    if (!this.interValId) {
      this.interValId = setTimeout(e => {
        const {chatCallStatus} = this.props;
        if (chatCallStatus.status === type) {
          dispatch(chatRejectCall(chatCallStatus.call));
          this.stopRingtone(type);
          this.interValId = window.clearInterval(this.interValId);
        }
      }, timeout);
    }
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    const {chatCallStatus} = this.props;
    const {chatCallStatus: oldChatCallStatus} = prevProps;
    const {status: oldStatus} = oldChatCallStatus;
    const {status} = chatCallStatus;
    if (oldStatus !== status) {
      this.interValId = window.clearInterval(this.interValId);
      if (status === CHAT_CALL_STATUS_INCOMING) {
        this.setTimeoutForDropping(CHAT_CALL_STATUS_INCOMING, DROPPING_INCOMING_TIME_OUT);
        this.playRingtone(CHAT_CALL_STATUS_INCOMING);
      } else {
        if (status === CHAT_CALL_STATUS_OUTGOING) {
          this.setTimeoutForDropping(CHAT_CALL_STATUS_OUTGOING, DROPPING_OUTGOING_TIME_OUT);
          this.playRingtone(CHAT_CALL_STATUS_OUTGOING);
        }
        if (!status || status === CHAT_CALL_STATUS_STARTED) {
          this.stopRingtone(CHAT_CALL_STATUS_OUTGOING);
          this.stopRingtone(CHAT_CALL_STATUS_INCOMING);
          if (!status) {
            this.refo.current.setState({x: 0, y: 0});
            this.setState({showControl: true});
          }
        }
      }
    }
  }

  componentWillUnmount() {
    this.setState({})
  }

  onCallBoxClick(e) {
    const {dispatch, chatCallBoxShowing} = this.props;
    const {thread, contact} = chatCallBoxShowing;
    dispatch(chatCallBoxShowingAction(CHAT_CALL_BOX_COMPACTED, thread, contact));
  }

  playRingtone(type) {
    const {callChatSettings} = this.props;
    if (type === CHAT_CALL_STATUS_INCOMING) {
      this.ringtone.currentTime = 0;
      this.ringtone.muted = false;
      if (callChatSettings[CHAT_SETTING_KEYS.CALL.RING_TONE_SOUND]) {
        this.ringtone.play()
      }
    } else if (type === CHAT_CALL_STATUS_OUTGOING) {
      this.callingTone.currentTime = 0;
      this.callingTone.muted = false;
      if (callChatSettings[CHAT_SETTING_KEYS.CALL.CALL_TONE_SOUND]) {
        this.callingTone.play();
      }
    }
  }

  stopRingtone(type) {
    if (type === CHAT_CALL_STATUS_INCOMING) {
      this.ringtone.muted = true;
      this.ringtone.pause();
      this.ringtone.currentTime = 0;
    } else if (type === CHAT_CALL_STATUS_OUTGOING) {
      this.callingTone.muted = true;
      this.callingTone.pause();
      this.callingTone.currentTime = 0;
    }
  }

  hideOrShowControls() {
    this.setState({
      showControl: !this.state.showControl
    })
  }

  render() {
    const {chatCallStatus, chatCallBoxShowing, threadObject} = this.props;
    const {showControl} = this.state;
    const {showing: callBoxShowingType, thread} = chatCallBoxShowing;
    const {status, call} = chatCallStatus;
    const incomingCondition = status === CHAT_CALL_STATUS_INCOMING;
    const {thread: currentThread, threadFetching} = threadObject;
    const fullScreenCondition = callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN || mobileCheck();
    const classNames = classnames({
      [style.CallBox]: true,
      [style["CallBox--showing"]]: callBoxShowingType === CHAT_CALL_BOX_NORMAL || callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN,
      [style["CallBox--fullScreen"]]: callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN || mobileCheck(),
      [style["CallBox--calling"]]: !incomingCondition,
      [style["CallBox--group"]]: thread && isGroup(thread)
    });

    const callBoxDraggableClassNames = classnames({
      [style.CallBox__DraggableContainer]: true,
      [style["CallBox__DraggableContainer--fullScreen"]]: callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN || mobileCheck(),
      [style["CallBox__DraggableContainer--showing"]]: callBoxShowingType === CHAT_CALL_BOX_NORMAL || callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN,
      [style["CallBox__DraggableContainer--fullScreen"]]: callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN || mobileCheck(),
      [style["CallBox__DraggableContainer--noThreadOpened"]]: (!currentThread.id && !threadFetching),
      [style["CallBox__DraggableContainer--calling"]]: !incomingCondition,
      [style["CallBox__DraggableContainer--group"]]: thread && isGroup(thread),
      [style["CallBox__DraggableContainer--showing"]]: callBoxShowingType === CHAT_CALL_BOX_NORMAL || callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN,
    });

    const callBoxHeadClassNames = classnames({
      [style.CallBox__Head]: true,
      [style["CallBox__Head--hide"]]: !showControl && fullScreenCondition
    });
    const CallBoxControlSetClassNames = classnames({
      [style.CallBox__ControlSet]: true,
      [style["CallBox__ControlSet--hide"]]: !showControl && fullScreenCondition
    });

    return <Draggable bounds="parent" disabled={mobileCheck() || fullScreenCondition} ref={this.refo}>
      <Container className={callBoxDraggableClassNames}>
        <Container className={classNames} id="chat-call-box">

          <Container className={callBoxHeadClassNames} onClick={this.onCallBoxClick}>
            <CallBoxHead chatCallStatus={chatCallStatus} thread={thread} chatCallBoxShowing={chatCallBoxShowing}
                         onCallBoxClick={this.onCallBoxClick}/>
          </Container>

          {(callBoxShowingType === CHAT_CALL_BOX_NORMAL || callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN) &&
          <Fragment>
            <Container className={style.CallBox__Scene} onClick={fullScreenCondition && this.hideOrShowControls}>
              <>
                {isGroup(thread) ?
                  <CallBoxSceneGroup chatCallStatus={chatCallStatus} chatCallBoxShowing={chatCallBoxShowing}/>
                  :
                  <CallBoxScenePerson chatCallStatus={chatCallStatus} chatCallBoxShowing={chatCallBoxShowing}/>
                }
                {(isRecording(call) || isScreenShare(call)) &&
                <Container className={style.CallBox__RecordingContainer} alignItems={fullScreenCondition ? "flex-start" : "center"}>
                  {isRecording(call) && <CallBoxRecording call={call}/>}
                  {isScreenShare(call) && <CallBoxRecording call={call} isScreenShare/>}
                </Container>
                }
              </>
            </Container>
            <Container className={CallBoxControlSetClassNames}>
              <CallBoxControlSet stopRingtone={this.stopRingtone} className={style.CallBox__ControlSet}/>
            </Container>
          </Fragment>
          }


        </Container>
      </Container>
    </Draggable>
  }
}