import React, {Component, Fragment} from "react";
import {connect} from "react-redux";
import Cookies from "js-cookie";
import classnames from "classnames";
import {
  isScreenShare,
  isScreenShareOwnerIsMe,
  isVideoCall,
  mobileCheck,
  sortCallParticipantsBy
} from "../utils/helpers";

//strings
import {SHOW_CALL_BUTTON} from "../constants/cookieKeys";
import {
  CHAT_CALL_BOX_COMPACTED,
  CHAT_CALL_BOX_FULL_SCREEN,
  CHAT_CALL_STATUS_INCOMING,
  CHAT_CALL_STATUS_OUTGOING,
  CHAT_CALL_STATUS_STARTED,
  SHOW_CALL_BUTTONS_EVENT
} from "../constants/callModes";

//actions
import {
  chatAcceptCall,
  chatCallMuteParticipants,
  chatCallParticipantListChange,
  chatCallTurnOffVideo,
  chatCallTurnOnVideo,
  chatCallUnMuteParticipants,
  chatRejectCall
} from "../actions/chatActions";

//components
import CallBoxControlSetMore from "./CallBoxControlSetMore";
import Container from "../../../Talk-ui-kit/src/container";
import {ButtonFloating} from "../../../Talk-ui-kit/src/button";
import {
  MdCall,
  MdMicOff,
  MdMic,
  MdVideocam,
  MdMoreHoriz,
  MdOutlineScreenShare,
  MdVideocamOff
} from "react-icons/md";

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

//statics

//functions

@connect(store => {
  return {
    chatCallStatus: store.chatCallStatus,
    user: store.user.user,
    chatCallParticipantList: sortCallParticipantsBy(store.chatCallParticipantList.participants, "id"),
    chatCallBoxShowing: store.chatCallBoxShowing
  }
})
export default class CallBoxControlSet extends Component {

  constructor(props) {
    super(props);
    this.onDropCallClick = this.onDropCallClick.bind(this);
    this.onAcceptCallClick = this.onAcceptCallClick.bind(this);
    this.onMicClick = this.onMicClick.bind(this);
    this.onCamClick = this.onCamClick.bind(this);
    this.onMoreActionClick = this.onMoreActionClick.bind(this);
    this.state = {
      mic: true,
      cam: false,
      moreSettingShow: false,
      showCallButtons: Cookies.get(SHOW_CALL_BUTTON)
    }
    window.addEventListener(SHOW_CALL_BUTTONS_EVENT, e => {
      this.setState({
        showCallButtons: true
      });
    })
  }

  componentDidMount() {
    const {user, chatCallParticipantList, chatCallStatus} = this.props;
    const {showCallButtons} = this.state;
    const {call} = chatCallStatus;
    if (!showCallButtons) {
      this.setState({
        showCallButtons: Cookies.get(SHOW_CALL_BUTTON)
      });
    }
    if (chatCallParticipantList.length) {
      const participant = chatCallParticipantList.find(e => e.id === user.id);

      if (participant) {
        this.setState({
          cam: isVideoCall(call) ? participant.video === undefined ? true : participant.video : participant.video,
          mic: !participant.mute
        });
      }
    }
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    const {user, chatCallStatus, dispatch, chatCallParticipantList} = this.props;
    const {cam} = this.state;
    const {chatCallStatus: oldChatCallStatus} = prevProps;
    const {status: oldStatus} = oldChatCallStatus;
    const {status, call} = chatCallStatus;
    if (oldStatus !== status) {
      if (oldStatus === CHAT_CALL_STATUS_OUTGOING) {
        if (status === CHAT_CALL_STATUS_STARTED) {
          const {mic, cam} = this.state;
          const {callId} = call;
          const {user} = this.props;
          const timeoutCount = 500;
          if (!mic) {
            setTimeout(() => dispatch(chatCallMuteParticipants(callId, [user.id])), timeoutCount);
          }
          if (isVideoCall(call)) {
            if (!cam) {
              setTimeout(() => dispatch(chatCallTurnOffVideo(user.id)), timeoutCount);
            }
          } else {
            if (cam) {
              setTimeout(() => dispatch(chatCallTurnOnVideo(user.id)), timeoutCount);
            }
          }
        }
      } else if (oldStatus === CHAT_CALL_STATUS_INCOMING) {
        if (!cam && this.lastAcceptedCallIsVideo) {
          this.setState({
            cam: this.lastAcceptedCallIsVideo
          });
          setTimeout(() => dispatch(chatCallParticipantListChange([{id: user.id, video: true}])), 1000)

        }
        this.lastAcceptedCallIsVideo = false;
      }
    }
    if (chatCallParticipantList?.length) {
      const me = chatCallParticipantList.filter(e => e.id === user.id);
      const oldMe = prevProps.chatCallParticipantList.filter(e => e.id === user.id);
      if (me.length) {
        if (me[0].mute && (!oldMe || !oldMe[0].mute)) {
          if (this.state.mic) {
            this.setState({
              mic: false
            });
          }
        }
      }
    }
  }

  onDropCallClick(e) {
    e.stopPropagation();
    const {stopRingtone, dispatch, chatCallStatus} = this.props;
    const {call, status} = chatCallStatus;
    dispatch(chatRejectCall(call, status));
    stopRingtone(status);
  }

  onAcceptCallClick(isVideoCall, e) {
    (e || isVideoCall).stopPropagation();
    const {dispatch, chatCallStatus, stopRingtone} = this.props;
    const {call, status} = chatCallStatus;
    dispatch(chatAcceptCall(call, isVideoCall === true));
    this.lastAcceptedCallIsVideo = isVideoCall === true;
    stopRingtone(status);
  }


  onMicClick(e) {
    e.stopPropagation();
    const currentState = this.state.mic;
    const nextState = !currentState;
    const {chatCallStatus, user, dispatch} = this.props;
    const {status, call} = chatCallStatus;
    if (nextState) {
      dispatch(chatCallUnMuteParticipants(call.callId, [user.id], status !== CHAT_CALL_STATUS_STARTED));
    } else {
      dispatch(chatCallMuteParticipants(call.callId, [user.id], status !== CHAT_CALL_STATUS_STARTED));
    }
    this.setState({
      mic: nextState,
    })
  }

  onCamClick(e) {
    e.stopPropagation();
    const currentState = this.state.cam;
    const nextState = !currentState;
    const {chatCallStatus, user, dispatch} = this.props;
    const {status} = chatCallStatus;
    if (nextState) {
      dispatch(chatCallTurnOnVideo(user.id, status !== CHAT_CALL_STATUS_STARTED));
    } else {
      dispatch(chatCallTurnOffVideo(user.id, status !== CHAT_CALL_STATUS_STARTED));
    }
    this.setState({
      cam: nextState,
    })
  }

  onMoreActionClick(showing, e) {
    e && e.stopPropagation()
    this.setState({
      moreSettingShow: !this.state.moreSettingShow
    });
  }
  render() {
    const {chatCallStatus, buttonSize, chatCallBoxShowing, user} = this.props;
    const {mic, showCallButtons, moreSettingShow, cam} = this.state;
    const {status, call} = chatCallStatus;
    const {showing: callBoxShowingType} = chatCallBoxShowing;
    const showScreenShareIconCondition = isScreenShare(call) && isScreenShareOwnerIsMe(call?.screenShare, user);
    const incomingCondition = status === CHAT_CALL_STATUS_INCOMING;
    const fullScreenCondition = callBoxShowingType === CHAT_CALL_BOX_FULL_SCREEN || (mobileCheck() && callBoxShowingType !== CHAT_CALL_BOX_COMPACTED);
    const showVideoCallButtons = showCallButtons || !call?.group;
    const classNames = classnames({
      [style.CallBoxControlSet]: true,
      [style["CallBoxControlSet--fullScreen"]]: fullScreenCondition
    });
    const callDropClassNames = classnames({
      [style.CallBoxControlSet__Button]: true,
      [style.CallBoxControlSet__DropCall]: true
    });
    const callAcceptClassNames = classnames({
      [style.CallBoxControlSet__Button]: true,
      [style.CallBoxControlSet__AcceptCall]: true
    });
    const micOffOrOnClassNames = classnames({
      [style.CallBoxControlSet__Button]: true,
      [style.CallBoxControlSet__Mic]: true
    });
    const moreActionClassNames = classnames({
      [style.CallBoxControlSet__Button]: true,
      [style.CallBoxControlSet__MoreAction]: true
    });

    return <Container className={classNames}>
      <ButtonFloating onClick={this.onDropCallClick} size={buttonSize || "sm"} className={callDropClassNames}>
        <MdCall size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
      </ButtonFloating>
      {incomingCondition &&
      <>
        <ButtonFloating size={buttonSize || "sm"} className={callAcceptClassNames} onClick={this.onAcceptCallClick}>
          <MdCall size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
        </ButtonFloating>
        {showVideoCallButtons &&
        <ButtonFloating size={buttonSize || "sm"} className={callAcceptClassNames}
                        onClick={this.onAcceptCallClick.bind(this, true)}>
          <MdVideocam size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
        </ButtonFloating>
        }
      </>
      }
      {!incomingCondition &&
      <>
        {showVideoCallButtons &&
        <ButtonFloating onClick={this.onCamClick} size={buttonSize || "sm"} className={micOffOrOnClassNames}>
          {cam ?
            <MdVideocam size={style.iconSizeMd} style={{margin: "7px 5px"}}/> :
            <MdVideocamOff size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
          }
        </ButtonFloating>
        }
        <ButtonFloating onClick={this.onMicClick} size={buttonSize || "sm"} className={micOffOrOnClassNames}>

          {mic ?
            <MdMic size={style.iconSizeMd} style={{margin: "7px 5px"}}/> :
            <MdMicOff size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
          }
        </ButtonFloating>

      </>
      }

      {!incomingCondition && callBoxShowingType !== CHAT_CALL_BOX_COMPACTED &&
      <Fragment>

        <ButtonFloating onClick={this.onMoreActionClick.bind(this, true)} size={buttonSize || "sm"}
                        className={moreActionClassNames}>
          {showScreenShareIconCondition &&
          <Container className={style.CallBoxControlSet__ScreenShareIconContainer}>
            <MdOutlineScreenShare size={style.iconSizeMd} style={{margin: "7px 5px"}}/>
          </Container>
          }
          <MdMoreHoriz size={style.iconSizeMd} style={{margin: "7px 5px"}}/>

        </ButtonFloating>
        {moreSettingShow && <CallBoxControlSetMore onMoreActionClick={this.onMoreActionClick.bind(this)}/>}
      </Fragment>
      }


    </Container>
  }
}