/*
 * Copyright (C) 2022 Savoir-faire Linux Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with this program.  If not, see
 * <https://www.gnu.org/licenses/>.
 */
import { ConversationInfos, WebSocketMessageTable, WebSocketMessageType } from 'jami-web-common';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import { AlertSnackbarContext } from '../contexts/AlertSnackbarProvider';
import { useAuthContext } from '../contexts/AuthProvider';
import { useUserMediaContext } from '../contexts/UserMediaProvider';
import { useWebSocketContext } from '../contexts/WebSocketProvider';
import { ConversationMember } from '../models/conversation-member';
import { useConversationInfosQuery, useMembersQuery } from '../services/conversationQueries';
import { callTimeoutMs } from '../utils/constants';
import { AsyncSetState, SetState } from '../utils/utils';
import { useWebRtcManager } from '../webrtc/WebRtcManager';

export type CallRole = 'caller' | 'receiver' | undefined;

export type CallData = {
  conversationId: string;
  role: CallRole;
  withVideoOn?: boolean;
};

export enum CallStatus {
  Default,
  Loading,
  Ringing,
  Connecting,
  InCall,
  PermissionsDenied,
}

export enum VideoStatus {
  Off,
  Camera,
  ScreenShare,
}

export interface ICallManager {
  callData: CallData | undefined;
  callConversationInfos: ConversationInfos | undefined;
  callMembers: ConversationMember[] | undefined;

  remoteStreams: readonly MediaStream[];

  isAudioOn: boolean;
  setIsAudioOn: SetState<boolean>;
  videoStatus: VideoStatus;
  updateVideoStatus: AsyncSetState<VideoStatus>;
  isChatShown: boolean;
  setIsChatShown: SetState<boolean>;
  isFullscreen: boolean;
  setIsFullscreen: SetState<boolean>;
  callStatus: CallStatus;
  callStartTime: number | undefined;

  startCall: (conversationId: string, withVideoOn?: boolean) => void;
  acceptCall: (withVideoOn: boolean) => void;
  endCall: () => void;
}

export const useCallManager = () => {
  const { setAlertContent } = useContext(AlertSnackbarContext);
  const [callData, setCallData] = useState<CallData>();
  const webSocket = useWebSocketContext();
  const navigate = useNavigate();
  const { data: callConversationInfos } = useConversationInfosQuery(callData?.conversationId);
  const { data: callMembers } = useMembersQuery(callData?.conversationId);

  const {
    localStream,
    updateLocalStream,
    screenShareLocalStream,
    updateScreenShare,
    setAudioInputDeviceId,
    setVideoDeviceId,
    stopMedias,
  } = useUserMediaContext();
  const { account } = useAuthContext();
  const webRtcManager = useWebRtcManager();

  const [isAudioOn, setIsAudioOn] = useState(false);
  const [videoStatus, setVideoStatus] = useState(VideoStatus.Off);
  const [isChatShown, setIsChatShown] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [callStatus, setCallStatus] = useState(CallStatus.Default);
  const [callStartTime, setCallStartTime] = useState<number | undefined>(undefined);

  useEffect(() => {
    const callInviteListener = ({ conversationId, withVideoOn }: WebSocketMessageTable['onCallInvite']) => {
      if (callData) {
        // TODO: Currently, we display a notification if already in a call.
        //       In the future, we should handle receiving a call while already in another.
        setAlertContent({
          messageI18nKey: 'missed_incoming_call',
          messageI18nContext: { conversationId },
          severity: 'info',
          alertOpen: true,
        });
        return;
      }

      setCallData({ conversationId: conversationId, role: 'receiver', withVideoOn });
      navigate(`/conversation/${conversationId}`);
    };

    webSocket.bind(WebSocketMessageType.onCallInvite, callInviteListener);

    return () => {
      webSocket.unbind(WebSocketMessageType.onCallInvite, callInviteListener);
    };
  }, [webSocket, navigate, callData, setAlertContent]);

  const conversationId = callData?.conversationId;
  const contactUri = callMembers?.[0]?.contact.uri;
  const connectionInfos = contactUri ? webRtcManager.connectionsInfos[contactUri] : undefined;
  const remoteStreams = useMemo(() => connectionInfos?.remoteStreams || [], [connectionInfos]);
  const iceConnectionState = connectionInfos?.iceConnectionState;

  // TODO: Transform the effect into a callback
  const updateLocalStreams = webRtcManager.updateLocalStreams;
  useEffect(() => {
    if ((!localStream && !screenShareLocalStream) || !updateLocalStreams) {
      return;
    }

    updateLocalStreams(localStream, screenShareLocalStream);
  }, [localStream, screenShareLocalStream, updateLocalStreams]);

  const closeConnection = useCallback(() => {
    stopMedias();
    webRtcManager.clean();
  }, [stopMedias, webRtcManager]);

  // Tracks logic should be moved into UserMediaProvider
  useEffect(() => {
    if (localStream) {
      for (const track of localStream.getAudioTracks()) {
        track.enabled = isAudioOn;
        const deviceId = track.getSettings().deviceId;
        if (deviceId) {
          setAudioInputDeviceId(deviceId);
        }
      }
    }
  }, [isAudioOn, localStream, setAudioInputDeviceId]);

  // Tracks logic should be moved into UserMediaProvider
  useEffect(() => {
    if (localStream) {
      for (const track of localStream.getVideoTracks()) {
        track.enabled = videoStatus === VideoStatus.Camera;
        const deviceId = track.getSettings().deviceId;
        if (deviceId) {
          setVideoDeviceId(deviceId);
        }
      }
    }
  }, [videoStatus, localStream, setVideoDeviceId]);

  // Track logic should be moved into UserMediaProvider
  const updateVideoStatus = useCallback(
    async (newStatus: ((prevState: VideoStatus) => VideoStatus) | VideoStatus) => {
      if (typeof newStatus === 'function') {
        newStatus = newStatus(videoStatus);
      }

      const stream = await updateScreenShare(newStatus === VideoStatus.ScreenShare);
      if (stream) {
        for (const track of stream.getTracks()) {
          track.addEventListener('ended', () => {
            console.warn('Browser ended screen sharing');
            updateVideoStatus(VideoStatus.Off);
          });
        }
      }

      setVideoStatus(newStatus);
    },
    [videoStatus, updateScreenShare]
  );

  useEffect(() => {
    const onFullscreenChange = () => {
      setIsFullscreen(document.fullscreenElement !== null);
    };

    document.addEventListener('fullscreenchange', onFullscreenChange);
    return () => {
      document.removeEventListener('fullscreenchange', onFullscreenChange);
    };
  }, []);

  const startCall = useCallback(
    (conversationId: string, withVideoOn = false) => {
      setCallData({ conversationId, withVideoOn, role: 'caller' });
      if (callStatus === CallStatus.Default) {
        setCallStatus(CallStatus.Loading);
        updateLocalStream()
          .then(() => {
            const callInvite: WebSocketMessageTable['sendCallInvite'] = {
              conversationId: conversationId,
              withVideoOn,
            };

            setCallStatus(CallStatus.Ringing);
            setVideoStatus(withVideoOn ? VideoStatus.Camera : VideoStatus.Off);
            webSocket.send(WebSocketMessageType.sendCallInvite, callInvite);
          })
          .catch((e) => {
            console.error(e);
            setCallStatus(CallStatus.PermissionsDenied);
          });
      }
    },
    [webSocket, updateLocalStream, callStatus]
  );

  const acceptCall = useCallback(
    (withVideoOn: boolean) => {
      if (!callMembers || !conversationId) {
        console.warn('acceptCall without callMembers or conversationId');
        return;
      }
      setCallStatus(CallStatus.Loading);
      updateLocalStream()
        .then(() => {
          const callAccept: WebSocketMessageTable['sendCallJoin'] = {
            conversationId,
          };

          setVideoStatus(withVideoOn ? VideoStatus.Camera : VideoStatus.Off);
          setCallStatus(CallStatus.Connecting);
          console.info('Sending CallJoin', callAccept);
          webSocket.send(WebSocketMessageType.sendCallJoin, callAccept);
          // TODO: move this to "onWebRtcOffer" listener so we don't add connections for non-connected members
          callMembers.forEach((member) =>
            webRtcManager.addConnection(
              webSocket,
              account,
              member.contact.uri,
              callData,
              localStream,
              screenShareLocalStream
            )
          );
        })
        .catch((e) => {
          console.error(e);
          setCallStatus(CallStatus.PermissionsDenied);
        });
    },
    [
      account,
      callData,
      conversationId,
      localStream,
      callMembers,
      screenShareLocalStream,
      updateLocalStream,
      webRtcManager,
      webSocket,
    ]
  );

  useEffect(() => {
    if (callData?.role === 'caller' && callStatus === CallStatus.Ringing) {
      const callJoinListener = (data: WebSocketMessageTable['onCallJoin']) => {
        console.info('Received event on CallJoin', data, callData);
        if (data.conversationId !== conversationId) {
          console.warn('Wrong incoming conversationId, ignoring action');
          return;
        }

        setCallStatus(CallStatus.Connecting);

        webRtcManager.addConnection(webSocket, account, data.senderId, callData, localStream, screenShareLocalStream);
      };

      webSocket.bind(WebSocketMessageType.onCallJoin, callJoinListener);

      return () => {
        webSocket.unbind(WebSocketMessageType.onCallJoin, callJoinListener);
      };
    }
  }, [account, callData, callStatus, conversationId, localStream, screenShareLocalStream, webRtcManager, webSocket]);

  const endCall = useCallback(() => {
    if (!conversationId) {
      return;
    }

    const callExit: WebSocketMessageTable['sendCallExit'] = {
      conversationId,
    };

    console.info('Sending CallExit', callExit);
    closeConnection();
    webSocket.send(WebSocketMessageType.sendCallExit, callExit);
    setCallData(undefined);
    setCallStatus(CallStatus.Default);
    // TODO: write in chat that the call ended
  }, [webSocket, conversationId, closeConnection]);

  useEffect(() => {
    const callExitListener = (data: WebSocketMessageTable['onCallExit']) => {
      console.info('Received event on CallExit', data);
      if (data.conversationId !== conversationId) {
        console.warn('Wrong incoming conversationId, ignoring action');
        return;
      }

      endCall();
      // TODO: write in chat that the call ended
    };

    webSocket.bind(WebSocketMessageType.onCallExit, callExitListener);
    return () => {
      webSocket.unbind(WebSocketMessageType.onCallExit, callExitListener);
    };
  }, [webSocket, endCall, conversationId]);

  useEffect(() => {
    if (
      callStatus === CallStatus.Connecting &&
      (iceConnectionState === 'connected' || iceConnectionState === 'completed')
    ) {
      console.info('Changing call status to InCall');
      setCallStatus(CallStatus.InCall);
      setCallStartTime(Date.now());
    }
  }, [iceConnectionState, callStatus]);

  useEffect(() => {
    if (iceConnectionState === 'disconnected' || iceConnectionState === 'failed') {
      console.info('ICE connection disconnected or failed, ending call');
      endCall();
    }
  }, [iceConnectionState, callStatus, videoStatus, endCall]);

  useEffect(() => {
    const checkStatusTimeout = () => {
      if (callStatus !== CallStatus.InCall) {
        endCall();
      }
    };
    const timeoutId = setTimeout(checkStatusTimeout, callTimeoutMs);

    return () => {
      clearTimeout(timeoutId);
    };
  }, [callStatus, endCall]);

  return useMemo(
    () => ({
      callData,
      callConversationInfos,
      callMembers,
      remoteStreams,
      isAudioOn,
      setIsAudioOn,
      videoStatus,
      updateVideoStatus,
      isChatShown,
      setIsChatShown,
      isFullscreen,
      setIsFullscreen,
      callStatus,
      callStartTime,
      startCall,
      acceptCall,
      endCall,
    }),
    [
      callData,
      callConversationInfos,
      callMembers,
      remoteStreams,
      isAudioOn,
      videoStatus,
      setIsAudioOn,
      updateVideoStatus,
      isChatShown,
      setIsChatShown,
      isFullscreen,
      setIsFullscreen,
      callStatus,
      callStartTime,
      startCall,
      acceptCall,
      endCall,
    ]
  );
};
