import { useAuthData } from "any-hooks/auth/useAuthData";
import { AnyRemoteMainFlag, AnyRemoteSubFlag } from "any-hooks/types/socket";
import { UserData } from "any-hooks/types/user";
import { watch } from "vue";
import { useInjector, useRequest, useState } from "vue-vulcan";
import { useChannelStore } from "./useChannelStore";
import { useNetSocketStore } from "./useNetSocketStore";

type CallingState = 'net_error' | 'calling' | 'call_successed' | 'callin' | 'call_accepted' | 'connecting' | 'free';

interface Caller extends UserData {  
  action: AnyRemoteSubFlag | 'none';
  members?: string[];
  channel?: string;
}

/**  呼叫中心功能，可以主动呼叫联系人、回应对方的呼叫，以及监听相关用户的实时呼叫状态 */
export function useCallCenter() {  

  const { sendMsg, currentMsg } = useInjector(useNetSocketStore);
  const { authData } = useInjector(useAuthData);
  const [, changeCallingState] = useRequest('/updateUsersCallState', {auto: false});

  let timer;
  
  /** 主动呼叫功能 */
  const [target, setTarget]             = useState<Caller>(null);
  const [myCallState, setCallState]     = useState<CallingState>('free');
  const {currentChannel, channelMembers, isEmpty, createChannel, getTokenByChannel, updateMembers, clearChannel} = useInjector(useChannelStore);
  const callContact = (user: UserData) => {
    setTarget({...user, action: 'none'}); //保存呼叫目标的信息    
    createChannel().then( data => {
      setCallState('calling'); //主动呼叫别人时将自己的呼叫状态更改为‘calling’
      sendMsg({
        toID: user.id,
        toName: user.nickname,
        channelID: data.channel_id,
        msgMainFlag: 'CallOffer',
        msgSubFlag: 'Request',
        msgData: {
          members: channelMembers.value
        }
      })
    })  
    //18S后若本地用户仍处于主动呼叫状态，则自动挂断
    timer = setTimeout(() => {
      if(myCallState.value === 'calling') hangup();
    }, 18000)
  }

  /** 回应呼叫功能 */
  const answerCaller = (subFlag: AnyRemoteSubFlag, user?: UserData) => {
    if(subFlag === 'Connect') {      
      getTokenByChannel(caller.value.channel).then( _ => setCallState('call_accepted')); 
      updateMembers(caller.value.members, 'join');
    };

    const target = user || caller.value;
    sendMsg({      
      toID: target.id,
      toName: target.nickname,
      msgMainFlag: 'CallAnswer',
      msgSubFlag: subFlag
    })
    clearTimeout(timer);
  }

  /** 呼叫监听功能  */
  const [caller, setCaller] = useState<Caller>(null);    
  // 监听来自其他用户的呼叫请求
  watch(currentMsg, msg => {
    if(msg.msgMainFlag !== 'CallOffer') return;
    switch(msg.msgSubFlag) {
      case 'Request':
        // 本地呼叫状态为free时，变更为callin;不为free，则发送繁忙的回应。
        console.log(`${currentMsg.value.fromName}呼叫，我目前的状态${myCallState.value}`)
        if(myCallState.value === 'free') {
          setCallState('callin');
          setCaller({      
            id: msg.fromID,
            nickname: msg.fromName,  
            action: msg.msgSubFlag,
            channel: msg.channelID,
            members: msg.msgData?.members || []
          })
        } else{          
          answerCaller('Busying', {id: msg.fromID, nickname: msg.fromName});
        } 
        //15S秒后若本地用户仍然处于被呼叫状态，则自动发出繁忙恢复，且将状态恢复为free
        timer = setTimeout( () => {
          if(myCallState.value === 'callin'){
            answerCaller('Busying', {id: currentMsg.value.fromID, nickname: currentMsg.value.fromName});
            setCallState('free');
          }
        }, 15000)     
      break;
      case 'Hangup':
        //对方中断呼叫，则将呼叫状态改为free
        setCallState('free'); 
        setCaller({      
          id: msg.fromID,
          nickname: msg.fromName,  
          action: msg.msgSubFlag,
          channel: msg.channelID,
          members: msg.msgData?.members || []
        })
      break;
    }
  })
  // 监听呼叫目标的回应
  watch(currentMsg, msg => {
    if(msg.msgMainFlag !== 'CallAnswer') return;
    setTarget({...target.value, action: msg.msgSubFlag});
    switch(msg.msgSubFlag) {
      case 'Connect':
        setCallState('call_successed');
        updateMembers([msg.fromID], 'join');
      break;
      case 'Busying':
      case 'Hangup':
        setCallState(isEmpty.value ? 'free' : 'connecting');
      break;
    }
  })  

  /** 呼叫挂断功能 */  
  const hangup = (type?: 'leave' | 'cancel') => {    
    let flag: AnyRemoteMainFlag, toID: string;
    switch(myCallState.value) {
      default:
        flag = 'ChannelChat';
        toID = '-2'; // '-2'表示向频道发送消息
      break;      
      case 'calling':
        flag = 'CallOffer';
        toID = target.value?.id;
      break;
      case 'callin':
        flag = 'CallAnswer';
        toID = caller.value?.id;
      break;
    } 
    
    sendMsg({      
      channelID: currentChannel.value?.channel_id,
      msgMainFlag: flag,
      msgSubFlag: 'Hangup',
      toID
    })
    isEmpty.value && setCallState('free');
    type === 'leave' && setCallState('free');
    setTarget(null);
    setCaller(null);
    clearTimeout(timer);
  }

  /** 监听呼叫状态，当状态变回free时，重置channel的信息,同时向服务器广播  */
  watch(myCallState, state => {
    console.log('state', state)
    if(state === 'free') {
      clearChannel();
      sendMsg({
        msgMainFlag: 'NotifyUpdateUserList',
        msgSubFlag: "UpdateUserList",
        toID: '0'
      })
    }     
    changeCallingState({channel_id: currentChannel.value?.channel_id, userIDs: JSON.stringify([
      {userID: authData.value.id, callState: state==='free' ? 'idle' : state==='calling' ? 'callout' : 'callin'},
      {userID: target.value?.id || caller.value?.id, callState: state==='free' ? 'idle' : 'callin'}
    ])});
  })

  return {
    /** 呼叫远程联系人 @param UserData */
    callContact,    
    /** 回应远程联系人的呼叫 @param AnyRemoteSubFlag  */
    answerCaller,
    /** 挂断当前呼叫  */
    hangup,
    /** 被本地用户呼叫目标联系人  */
    target,
    setTarget,
    /** 向本地用户发起呼叫的远程联系人 */
    caller,
    setCaller,
    /** 本地用户的呼叫状态 */
    myCallState,
  }
}