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' | 'callout' | 'calling' | 'call_successed' | 'callin' | 'call_accepted' | 'connecting' | 'idle';

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

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

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

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

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

    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，则发送繁忙的回应。
        if(myCallState.value === 'idle') {
          setCaller({      
            id: msg.fromID,
            nickname: msg.fromName,  
            avatar: msg.msgData.avatar,
            action: msg.msgSubFlag,
            state: 'callout',
            channel: msg.channelID            
          })
          setCallState('callin');
        } else{          
          answerCaller('Busying', {id: msg.fromID, nickname: msg.fromName});
        } 
        //15S秒后若本地用户仍然处于被呼叫状态，则自动发出繁忙恢复，且将状态恢复为idle
        timer = setTimeout( () => {
          if(myCallState.value === 'callin'){
            answerCaller('Busying', {id: msg.fromID, nickname: msg.fromName});
            setCallState('idle');
          }
        }, 15000)     
      break;
      case 'Hangup':
        //对方中断呼叫，则将呼叫状态改为idle
        setCallState('idle'); 
        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('calling');
        setInChannel(true);
        target.value.state = 'calling';
        updateMembers();
      break;
      case 'Busying':
      case 'Hangup':
        target.value.state = 'idle';        
        setCallState(!isInChannel.value ? 'idle' : 'calling');        
      break;
    }
  })  

  /** 呼叫挂断功能 */  
  const hangup = (type?: 'leave' | 'cancel') => {    
    let flag: AnyRemoteMainFlag, toID: string;
    switch(myCallState.value) {
      default:
        flag = 'ChannelChat';
        toID = '-2'; // '-2'表示向频道发送消息
      break;      
      case 'callout':
        flag = 'CallOffer';
        // flag = 'CallAnswer'
        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
    })
    setCallState('idle');    
    // type === 'leave' && setCallState('idle');
    setTarget(null);
    setCaller(null);
    clearTimeout(timer);
  }

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

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