import React, {Component} from "react";
import ReactDOM from "react-dom";
import {connect} from "react-redux";
import classnames from "classnames";
import {
  findLocalStreams,
  findRemoteStreams,
  isScreenShare,
  isScreenShareOwnerIsMe,
  isVideoCall,
  mobileCheck
} from "../utils/helpers";


//strings
import {
  CALL_DIV_ID,
  CHAT_CALL_BOX_FULL_SCREEN
} from "../constants/callModes";

//actions

//components
import Container from "../../../Talk-ui-kit/src/container";
import {MdMicOff} from "react-icons/md";

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

//statics

//functions
function fixVideoTag(tag, classNames) {
  tag.setAttribute("class", classNames);
  tag.removeAttribute("height");
  tag.removeAttribute("width");
  tag.disablePictureInPicture = true;
}
function fixInjectVideoTag(tag, parent) {
  if (!tag || !parent) {
    return;
  }
  parent.querySelector('video') && parent.querySelector('video').remove();
  parent.append(tag);
}

@connect()
export default class CallBoxScenePersonVideo extends Component {

  constructor(props) {
    super(props);
    this.remoteVideoRef = React.createRef();
    this.localVideoRef = React.createRef();
    this.remoteVideoInScreenSharingRef = React.createRef();
  }

  _getTags(call, user) {
    const {uiElements} = call;
    const isVideoCalling = isVideoCall(call);
    const isScreenSharing = isScreenShare(call);
    const isScreenSharingOwnerIsMe = isScreenSharing && isScreenShareOwnerIsMe(call?.screenShare, user);
    let {video: remoteVideo} = findRemoteStreams(user, call.otherClientDtoList, uiElements);
    const {video: localVideo} = findLocalStreams(user, uiElements)
    const {video: screenShareVideo} = uiElements.screenShare;

    return {remoteVideo, localVideo, screenShareVideo, isScreenSharing, isScreenSharingOwnerIsMe, isVideoCalling}
  }

  _injectVideos() {
    const {user, chatCallStatus, isVideoCall, isVideoIncluded} = this.props;
    const {call} = chatCallStatus;
    const {uiElements} = call;
    if (uiElements) {
      const remoteVideoTag = ReactDOM.findDOMNode(this.remoteVideoRef.current);
      const localVideoTag = ReactDOM.findDOMNode(this.localVideoRef.current);
      const {
        remoteVideo,
        localVideo,
        screenShareVideo,
        isScreenSharing,
      } = this._getTags(call, user);
      screenShareVideo && fixVideoTag(screenShareVideo, style.CallBoxScenePersonVideo__SideCamVideo);
      remoteVideo && fixVideoTag(remoteVideo, isScreenSharing ? style.CallBoxScenePersonVideo__SideCamVideo : style.CallBoxScenePersonVideo__MainCamVideo);
      localVideo && fixVideoTag(localVideo, style.CallBoxScenePersonVideo__SideCamVideo);
      if (isScreenSharing) {
        const remoteVideoInScreenSharingRef = ReactDOM.findDOMNode(this.remoteVideoInScreenSharingRef.current);
        fixInjectVideoTag(screenShareVideo, remoteVideoTag);
        if (isVideoIncluded) {
          fixInjectVideoTag(localVideo, localVideoTag)
          fixInjectVideoTag(remoteVideo, remoteVideoInScreenSharingRef)
        }
      } else {
        fixInjectVideoTag(localVideo, localVideoTag);
        fixInjectVideoTag(remoteVideo, remoteVideoTag);
      }
    }
  }

  componentDidMount() {
    this._injectVideos();
  }

  componentWillUnmount() {
    const {user, chatCallStatus} = this.props;
    const {call} = chatCallStatus;
    const {uiElements} = call;
    if (uiElements) {
      const {video: remoteVideo} = isScreenShare(call) ? uiElements.screenShare : findRemoteStreams(user, call.otherClientDtoList, uiElements);
      const {video: localVideo} = findLocalStreams(user, uiElements);
      const callDivTag = document.getElementById(CALL_DIV_ID);
      callDivTag.append(remoteVideo);
      callDivTag.append(localVideo);
    }
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    const {call: oldCall} = prevProps.chatCallStatus;
    const {call} = this.props.chatCallStatus;
    if (oldCall) {
      if (!oldCall.uiRemoteElements) {
        this._injectVideos();
      }
    }
  }

  render() {
    const {
      chatCallStatus,
      chatCallBoxShowing,
      user,
      chatCallParticipantList,
      isVideoIncluded
    } = this.props;
    const {status, call} = chatCallStatus;
    const fullScreenCondition = chatCallBoxShowing.showing === CHAT_CALL_BOX_FULL_SCREEN || mobileCheck();
    const sideUserFromParticipantList = chatCallParticipantList.find(participant => user.id !== participant.id);
    const selfFromParticipantList = chatCallParticipantList.find(participant => user.id === participant.id);
    const isScreenSharing = isScreenShare(call);
    const {uiElements} = call;
    const isRemoteVideoExisted = (sideUserFromParticipantList && uiElements[sideUserFromParticipantList?.id]?.video);
    const isLocalVideoExisted = uiElements && uiElements[user?.id]?.video;

    const classNames = classnames({
      [style.CallBoxScenePersonVideo]: true,
      [style["CallBoxScenePersonVideo--fullScreen"]]: fullScreenCondition
    });

    const callBoxSceneCamContainerClassName = classnames({
      [style.CallBoxScenePersonVideo__Cams]: true,
      [style["CallBoxScenePersonVideo__Cams--fullScreen"]]: fullScreenCondition,
      [style["CallBoxScenePersonVideo__Cams--fullWidth"]]: fullScreenCondition && isScreenSharing
    });


    const MuteContainer = ({participant}) => {
      if (!participant?.mute) {
        return;
      }
      return <Container center>
        <MdMicOff size={style.iconSizeXs}
                  color={style.colorAccent}
                  style={{margin: "3px 4px"}}/>
      </Container>
    }

    return <Container className={classNames}>
      <Container className={callBoxSceneCamContainerClassName}>
        {(isRemoteVideoExisted || isLocalVideoExisted || isScreenSharing) &&
        <>
          {!isScreenSharing &&
          <MuteContainer
            participant={isRemoteVideoExisted || isScreenSharing ? sideUserFromParticipantList : selfFromParticipantList}/>
          }
          <Container className={style.CallBoxScenePersonVideo__MainCam}
                     ref={isRemoteVideoExisted || isScreenSharing ? this.remoteVideoRef : this.localVideoRef}/>
        </>
        }
        {isVideoIncluded &&
        <Container className={style.CallBoxScenePersonVideo__SideCams}>
          {((isRemoteVideoExisted && isLocalVideoExisted) || (isScreenSharing && isLocalVideoExisted)) &&
          <Container className={style.CallBoxScenePersonVideo__SideCam}
                     ref={this.localVideoRef}>
            <MuteContainer participant={selfFromParticipantList}/>
          </Container>
          }
          {(isScreenSharing && isRemoteVideoExisted) &&
          <Container relative className={style.CallBoxScenePersonVideo__SideCam}
                     ref={this.remoteVideoInScreenSharingRef}>
            <MuteContainer participant={sideUserFromParticipantList}/>
          </Container>
          }
        </Container>
        }
      </Container>
    </Container>
  }
}