/** 
                                ** 呼叫流程 **
    caller            --------------------------------------             callee
            ----------inviting--------------->
                                        <-------------alerting-------
            ----------confirmRing------------>
                                        <-------------answerCall-----
            ----------confirmCallee---------->
*/
let disp = require("./broadcast");
const CALLSTATUS = {
    idle: 0,
    inviting: 1,
    alerting: 2,
    confirmRing: 3, // caller
    receivedConfirmRing: 4, // callee
    answerCall: 5,
    receivedAnswerCall: 6,
    confirmCallee: 7
}
wx.WebIM.rtc = {
    // 用来放置本地客户端。
    client: null,
    // 用来放置本地音视频频轨道对象。
    localAudioTrack: null,
    localVideoTrack: null,
    timer: null
}

let emediaState = {
    callStatus: CALLSTATUS.idle,
    callDuration: '00:00',
    minisize: false,
    confr: {
        channel: '',
        token: '',
        type: null,
        callId: null,
        callerDevId: null,
        calleeDevId: null,
        confrName: '',
        callerIMName: '',
        calleeIMName: ''
    },
    gid: '',
    inviteModal: false,
    joinedMembers: [],
    invitedMembers: [],

    onMessage: function (message) {
        let me = emediaState
        console.log('msg', message)
        let msg = message
        // text invite message
        if (message.ext.action == 'invite') {
            console.log('收到邀请消息', message)
            message.calleeIMName = message.to
            message.callerIMName = message.from

            if (message.from == wx.WebIM.conn.context.jid.name) {
                return // 自己在另一端发出的邀请
            }
            if (emediaState.callStatus > CALLSTATUS.idle) { // 正忙
                if (message.ext.callId == emediaState.confr.callId) { // 多人会议中邀请别人
                    emediaState.callStatus = CALLSTATUS.alerting
                    emediaState.sendAlerting(message.from, message.ext.callerDevId, message.ext.callId) // 回复alerting消息
                } else {
                    emediaState.answerCall.call(emediaState, 'busy', { callId: message.ext.callId, callerDevId: message.ext.callerDevId, to: message.from })
                }
            }

            emediaState.updateConfr(message)
            emediaState.sendAlerting(message.from, message.ext.callerDevId, message.ext.callId) // 回复alerting消息
            emediaState.callStatus = CALLSTATUS.alerting // 更改为alerting状态
        }
        // CMD sessage
        if (msg.action === "rtcCall") {
            if (msg.from === wx.WebIM.conn.context.jid.name) {
                return // 多端情况， 另一端自己发的消息
            }
            let msgInfo = msg.ext
            let deviceId = '';
            let callerDevId = ''
            let callId = '';

            switch (msgInfo.action) {
                case "alert":
                    deviceId = msgInfo.calleeDevId
                    callerDevId = msgInfo.callerDevId
                    callId = msgInfo.callId
                    console.log('收到回复的alert', msg)
                    emediaState.confirmRing.call(emediaState, msg.from, deviceId, callerDevId, callId)
                    break;
                case "confirmRing":
                    console.log('收到confirmRing', msg)
                    if (msgInfo.calleeDevId != wx.WebIM.conn.context.jid.clientResource) {
                        console.log('不是自己设备的confirmRing', msg)
                        return // 多端情况另一端的消息
                    }
                    if (!msgInfo.status && emediaState.callStatus < CALLSTATUS.receivedConfirmRing) {
                        console.warn('邀请已失效')
                        wx.showToast({
                            title: "邀请已失效",
                            duration: 1000
                        });
                        emediaState.callStatus = CALLSTATUS.idle
                        emediaState.hangup()
                        return
                    }
                    deviceId = msgInfo.calleeDevId
                    emediaState.callStatus = CALLSTATUS.receivedConfirmRing
                    console.log('清除定时器2')
                    wx.WebIM.rtc.timer && clearTimeout(wx.WebIM.rtc.timer)
                    // disp.fire('emedia.confirmRing');

                    wx.showModal({
                        title: '提示',
                        content: '邀请你加入视频会议',
                        success(res) {
                            if (res.confirm) {
                                console.log('emediaState ---', emediaState)
                                if (emediaState.callStatus == 0) {
                                    return
                                }
                                me.answerCall.call(me, 'accept', msgInfo)
                                let pages = getCurrentPages();
                                let curPage = pages[pages.length - 1];
                                if (curPage.route !== "pages/chatroom/chatroom") {

                                    var nameList = {
                                        myName: wx.WebIM.conn.context.jid.name,
                                        your: msg.from,
                                        action: 'join',
                                        data: msg
                                    };

                                    if (msgInfo.ext && msgInfo.ext.groupId) {
                                        nameList.groupId = msgInfo.ext.groupId
                                    }
                                    wx.navigateTo({
                                        url: "../chatroom/chatroom?username=" + JSON.stringify(nameList)
                                    });
                                } else {
                                    disp.fire('emedia.confirmRing', msg);
                                }
                            } else {
                                me.answerCall.call(me, 'refuse', msgInfo)
                            }

                        },
                        fail() {
                            me.answerCall.call(me, 'refuse', msgInfo)
                        }
                    })
                    break;
                case "answerCall":
                    console.log('收到回复的answerCall', msg)
                    console.log('清除定时器1')
                    wx.WebIM.rtc.timer && clearTimeout(wx.WebIM.rtc.timer)

                    deviceId = msgInfo.calleeDevId

                    if (msgInfo.callerDevId != wx.WebIM.conn.context.jid.clientResource) {
                        console.log('不是自己设备的answerCall', msg)
                        return // 多端情况另一端的消息
                    }

                    emediaState.confirmCallee(msg.from, deviceId, msgInfo.result)

                    if (msgInfo.result !== 'accept') {
                        if (msgInfo.result === 'busy') {
                            console.error('对方正忙')
                            wx.showToast({
                                title: "对方正忙",
                                duration: 1000
                            });
                        } else if (msgInfo.result === 'refuse') {
                            console.error('对方已拒绝')
                            wx.showToast({
                                title: "对方已拒绝",
                                duration: 1000
                            });
                        }

                        if (emediaState.confr.type !== 2) { // 单人情况挂断，多人不挂断
                            emediaState.hangup()
                            disp.fire('hangup')
                            emediaState.callStatus = CALLSTATUS.idle
                        }
                    }
                    break;
                case "confirmCallee":
                    console.log('收到confirmCallee', msg)
                    if (msgInfo.calleeDevId != wx.WebIM.conn.context.jid.clientResource) {
                        if (msg.to == wx.WebIM.conn.context.jid.name) {
                            emediaState.hangup()
                            emediaState.callStatus = CALLSTATUS.idle
                            // disp.fire('hangup')
                            wx.showToast({
                                title: "已在其他设备处理",
                                duration: 2000
                            });
                            return console.error('已在其他设备处理')
                        }
                    }
                    else if (msg.ext.result != 'accept' && emediaState.callStatus != 7) {
                        // 不在通话中收到 busy refuse时挂断
                        emediaState.hangup()
                        disp.fire('hangup')

                        emediaState.callStatus = CALLSTATUS.idle
                        return
                    }
                    emediaState.callStatus = CALLSTATUS.confirmCallee
                    break;
                case "cancelCall":
                    console.log('收到cancelCall', msg)

                    if (msg.from == wx.WebIM.conn.context.jid.name) {
                        return // 多端情况另一端的消息
                    }
                    if (msg.from == emediaState.confr.callerIMName) {
                        emediaState.hangup()
                        disp.fire('hangup')
                        emediaState.callStatus = CALLSTATUS.idle
                    }
                    break;
                default:
                    console.log('unexpected action')
                    break;
            }
        }
    },

    // callee
    sendAlerting: (to, calleeDevId, callId) => {
        var id = wx.WebIM.conn.getUniqueId();            //生成本地消息id
        var msg = new wx.WebIM.message('cmd', id); //创建命令消息
        msg.set({
            to: to,
            action: 'rtcCall',
            ext: {
                action: 'alert',
                calleeDevId: wx.WebIM.conn.context.jid.clientResource,
                callerDevId: calleeDevId,
                callId: callId,
                ts: Date.now(),
                msgType: 'rtcCallWithAgora'
            },
            success: function (id, serverMsgId) {
                emediaState.callStatus = CALLSTATUS.alerting
            },
            fail: function (e) {
                console.log("Fail");
            }
        });

        console.log('被叫发出的alert: ', msg.body)
        wx.WebIM.conn.send(msg.body);
        wx.WebIM.rtc.timer = setTimeout(() => {
            console.log('定时器到期')
            emediaState.hangup()
            disp.fire('hangup')
            emediaState.callStatus = CALLSTATUS.idle
        }, 30000)
        console.log('设置定时器')
    },

    // caller
    confirmRing: function (to, calleeDevId, callerDevId, callId) {
        let me = emediaState;
        let confr = emediaState.confr
        let currentCallId = confr.callId
        let status = true
        console.log('confirmRing confr', confr)
        if (callerDevId !== wx.WebIM.conn.context.jid.clientResource) {
            console.warn('callerDevId 设备不相同')
            return
        }
        if (callId !== currentCallId) {
            console.warn('callId 不相同', callId)
            status = false
        }
        else if (emediaState.callStatus > 4 && confr.type != 2) { //已经在通话中
            status = false
        }

        var id = wx.WebIM.conn.getUniqueId();            //生成本地消息id
        var msg = new wx.WebIM.message('cmd', id); //创建命令消息
        msg.set({
            to: to,
            action: 'rtcCall',
            ext: {
                action: 'confirmRing',
                status: status, // TRUE为有效，FALSE为无效（miss）
                callerDevId: wx.WebIM.conn.context.jid.clientResource,
                calleeDevId: calleeDevId,
                callId: callId,
                ts: Date.now(),
                msgType: 'rtcCallWithAgora'
            },
            success: function (id, serverMsgId) {
                if (status) {
                    me.callStatus = CALLSTATUS.confirmRing;
                }
            },
            fail: function (e) {
                console.log("Fail");
            }
        });
        console.log('发送confirmRing', msg)
        wx.WebIM.conn.send(msg.body);
    },

    // callee
    answerCall: (result, info) => {
        info = info || {}
        var id = wx.WebIM.conn.getUniqueId();            //生成本地消息id
        var msg = new wx.WebIM.message('cmd', id); //创建命令消息
        let currentCallId = info.currentCallId || info.callId
        let callerDevId = info.callerDevId || emediaState.confr.callerDevId
        let to = info.to || emediaState.confr.callerIMName
        msg.set({
            to: to,
            action: 'rtcCall',
            ext: {
                action: 'answerCall',
                result: result, // busy/accept/refuse
                callerDevId: callerDevId,
                calleeDevId: wx.WebIM.conn.context.jid.clientResource,
                callId: currentCallId,
                ts: Date.now(),
                msgType: 'rtcCallWithAgora'
            },
            success: function (id, serverMsgId) {

            },
            fail: function (e) {
                console.log("Fail"); //如禁言、拉黑后发送消息会失败
            }
        });
        console.log('发送answerCall', msg)
        wx.WebIM.conn.send(msg.body);
    },

    // caller
    confirmCallee: function (to, calleeDevId, result) {
        let me = emediaState
        var id = wx.WebIM.conn.getUniqueId();
        var msg = new wx.WebIM.message('cmd', id);

        let confr = emediaState.confr
        let currentCallId = confr.callId

        if (!confr.calleeDevId && confr.type != 2) {
            emediaState.updateConfr({
                to: confr.confrName,
                ext: {
                    channelName: confr.channel,
                    token: confr.token,
                    type: confr.type,
                    callerDevId: confr.callerDevId,
                    calleeDevId: calleeDevId,
                    callId: confr.callId,
                    members: [{ name: 'name1', uid: 12345 }]
                },
                calleeIMName: confr.calleeIMName,
                callerIMName: confr.callerIMName
            })
        } else if (confr.calleeDevId != calleeDevId && confr.type != 2) {
            result = 'refuse'
        }

        msg.set({
            to: to,
            action: 'rtcCall',
            ext: {
                action: 'confirmCallee',
                result: result || 'accept', // busy/accept/refuse
                callerDevId: wx.WebIM.conn.context.jid.clientResource,
                calleeDevId: calleeDevId,
                callId: currentCallId,
                ts: Date.now(),
                msgType: 'rtcCallWithAgora'
            },
            success: function (id, serverMsgId) {
                me.callStatus = CALLSTATUS.confirmCallee
            },
            fail: function (e) {
                console.log("Fail")
            }
        });
        console.log('发送confirmCallee', msg)
        wx.WebIM.conn.send(msg.body);
    },

    cancelCall: function (to) {
        let me = emediaState
        var id = wx.WebIM.conn.getUniqueId();
        var msg = new wx.WebIM.message('cmd', id);
        let callerDevId = emediaState.confr.callerDevId
        let user = to || emediaState.confr.calleeIMName
        let currentCallId = emediaState.confr.callId
        if (!user) {
            console.log('-- to is undefined --')
            return
        }
        msg.set({
            to: user,
            action: 'rtcCall',
            ext: {
                action: 'cancelCall',
                callerDevId: callerDevId,
                callId: currentCallId,
                ts: Date.now(),
                msgType: 'rtcCallWithAgora'
            },
            success: function (id, serverMsgId) {
                me.callStatus = CALLSTATUS.idle
            },
            fail: function (e) {
                console.log("Fail");
            }
        });
        console.log('发送取消消息', msg)
        wx.WebIM.conn.send(msg.body);
    },

    hangup: () => {
        emediaState.callStatus = CALLSTATUS.idle
        emediaState.cancelCall()
        // dispatch(Creators.setCallDuration('00:00'))
        // dispatch(Creators.setMinisize(false))
        // dispatch(Creators.resetAll())
        // dispatch(Creators.setJoinedMembers([]))
        // dispatch(Creators.setInvitedMembers([]))
        // dispatch(Creators.updateConfr({
        // 	to: '',
        // 	ext: {}
        // }))
        emediaState.updateConfr({})
    },

    updateConfr: function (msg) {
        let confrInfo = msg.ext || {}
        let groupId
        let confr = {
            channel: confrInfo.channelName,
            token: confrInfo.token,
            type: confrInfo.type,
            callId: confrInfo.callId,
            callerDevId: confrInfo.callerDevId,
            calleeDevId: confrInfo.calleeDevId
        }
        if (confrInfo.type === 2) {
            confr.confrName = msg.to
        } else {
            confr.confrName = msg.from
        }

        if (msg.calleeIMName) {
            confr.calleeIMName = msg.calleeIMName
        }

        if (msg.callerIMName) {
            confr.callerIMName = msg.callerIMName
        }
        if (confrInfo.ext) {
            groupId = confrInfo.ext.groupId
            confr.gid = groupId
        }

        emediaState.confr = confr
        //return confrInfo.ext ? emediaState.confr.gid = groupId : emediaState.confr = confr
    },

    setConf: function (prop, value) {
        if (typeof prop == 'object') {
            for (let key in prop) {
                emediaState.confr[key] = prop[key]
            }
            return
        }
        emediaState.confr[prop] = value
    }
}

module.exports = emediaState


