package com.wdkl.app.ncs.callingbed.fragment

import android.os.Handler
import android.os.Looper
import android.os.SystemClock
import android.text.TextUtils
import android.util.Log
import android.view.View
import com.google.gson.Gson
import com.wdkl.app.ncs.callingbed.R
import com.wdkl.app.ncs.callingbed.helper.RingPlayHelper
import com.wdkl.ncs.android.lib.utils.AppTool
import com.wdkl.ncs.android.lib.utils.showMessage
import com.wdkl.ncs.android.middleware.common.Constant
import com.wdkl.ncs.android.middleware.common.MessageEvent
import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
import com.wdkl.ncs.android.middleware.tcp.channel.VideoUtil
import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
import com.wdkl.ncs.android.middleware.utils.StringUtil
import com.wdkl.ncs.janus.client.CallSessionCallback
import com.wdkl.ncs.janus.client.JanusClient
import com.wdkl.ncs.janus.client.VideoRoomCallback
import com.wdkl.ncs.janus.entity.Room
import com.wdkl.ncs.janus.rtc.WebRTCEngine
import com.wdkl.ncs.janus.util.EnumType
import com.wdkl.ncs.janus.util.JanusConstant
import kotlinx.android.synthetic.main.sky_voice_call_layout.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.webrtc.SurfaceViewRenderer
import java.math.BigInteger

class SkyCallFragment: BaseCallFragment(), CallSessionCallback {
    private val TAG = "SkyCallFragment"

    //来电设备id
    var fromId: Int = -1

    private var interactionVO: InteractionVO? = null

    private var localSurfaceView: SurfaceViewRenderer? = null
    private var remoteSurfaceView: SurfaceViewRenderer? = null

    private var janusClient: JanusClient? = null
    private var room: Room?=null
    private var videoRoomCallback: VideoRoomCallback? = null

    private val handler = Handler(Looper.getMainLooper())

    private var visiting: Boolean = false

    private var audioCall: Boolean = true

    private var callEnded: Boolean = false

    private var outGoing: Boolean = false

    private var callSuccess: Boolean = false

    override fun getLayId(): Int {
        return R.layout.sky_voice_call_layout
    }

    override fun init() {
        //初始化计时器
        initCountDownTimer(sky_voice_call_timeout)
        //tcp参数
        if (tcpModel != null) {
            fromId = tcpModel!!.fromId
            interactionVO = Gson().fromJson(tcpModel!!.data.toString(), InteractionVO::class.java)
        }

        //初始化 engine
        WebRTCEngine.getInstance().init(true, this.context)
        //初始化 janusClient
        janusClient = JanusClient(JanusConstant.JANUS_URL, Constant.SIP_ID.toBigInteger())

        when (callState) {
            0 -> {
                //去电
                outGoing = true
                startOutgoing()
                RingPlayHelper.playRingTone(baseActivity, R.raw.ring_back2, true)

                janusClient!!.callState = EnumType.CallState.Outgoing
                room = Room(Constant.SIP_ID.toBigInteger())
            }

            1 -> {
                //来电
                outGoing = false
                showIncomingCall()
                RingPlayHelper.playRingTone(baseActivity, R.raw.ring_tone, true)

                janusClient!!.callState = EnumType.CallState.Incoming
                room = Room(Constant.TARGET_SIP.toBigInteger())
            }

            /*2 -> {
                //探视
                outGoing = true
                visiting = true
                acceptCall()
                //因为探视请求是由探视机发起的，所以在每一条的探视交互记录中的from为探视机
                startVisiting(interactionVO!!.fromSipId)
            }*/
        }

        videoRoomCallback = VideoRoomCallback(janusClient, room, Constant.SIP_ID.toBigInteger())
        videoRoomCallback!!.callSessionCallback = this
        janusClient!!.setJanusCallback(videoRoomCallback)
    }

    override fun bindEvent() {
        //去电取消或通话挂断
        sky_voice_call_hangup.setOnClickListener {
            RingPlayHelper.stopRingTone()
            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
                //结束sip通话
                Constant.CALL_STATE = Constant.CALL_STANDBY
                sky_voice_call_timer.stop()
                callEnd(true)
            } else {
                Constant.CALL_STATE = Constant.CALL_STANDBY
                VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
                cancelCall()
            }
        }

        //来电拒绝
        sky_voice_call_ring_reject.setOnClickListener {
            RingPlayHelper.stopRingTone()
            Constant.CALL_STATE = Constant.CALL_STANDBY
            VoiceUtil.rejectAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
            callEnd(false)
        }

        //来电接听
        sky_voice_call_ring_pickup_audio.setOnClickListener {
            RingPlayHelper.stopRingTone()
            Constant.CALL_STATE = Constant.CALL_INCOMING
            VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
            acceptCall()
            janusClient!!.connect()
        }
    }

    override fun destroy() {
        cancelTimer()
        Constant.CALL_STATE = Constant.CALL_STANDBY
        if (sky_voice_call_timer != null) {
            sky_voice_call_timer.stop()
        }
        RingPlayHelper.stopRingTone()
    }

    private fun startOutgoing() {
        callSuccess = false
        sky_voice_call_hangup.isEnabled = false
        VoiceUtil.startAudioCall(Constant.DEVICE_ID)
        Constant.CALL_STATE = Constant.CALL_OUTGOING
        sky_voice_call_timeout.visibility = View.VISIBLE
        sky_voice_call_timer.visibility = View.GONE
        startTimer()

        AppTool.Time.delay(3000) {
            Log.d("tcp", "call success: $callSuccess")
            if (!callSuccess) {
                //呼叫失败
                showMessage(R.string.call_init_error)
                RingPlayHelper.stopRingTone()
                cancelCall()
            }
        }
    }

    //去电界面
    private fun showOutgoingCall() {
        Constant.CALL_STATE = Constant.CALL_OUTGOING
        sky_voice_call_calling_text.text = StringUtil.getResString(R.string.call_success)
        sky_voice_call_outgoing.visibility = View.VISIBLE
        sky_voice_call_incoming.visibility = View.GONE
        sky_voice_call_timeout.visibility = View.VISIBLE
        sky_voice_call_timer.visibility = View.GONE
        startTimer()
    }

    //来电界面
    private fun showIncomingCall() {
        Constant.CALL_STATE = Constant.CALL_INCOMING
        sky_voice_call_calling_text.text = StringUtil.getResString(R.string.call_incoming)
        sky_voice_call_outgoing.visibility = View.GONE
        sky_voice_call_incoming.visibility = View.GONE
        sky_voice_call_timeout.visibility = View.GONE
        sky_voice_call_timer.visibility = View.GONE
        cancelTimer()
    }

    //开始接听
    private fun acceptCall() {
        sky_voice_call_calling_text.text = StringUtil.getResString(R.string.call_connecting)
        sky_voice_call_outgoing.visibility = View.VISIBLE
        sky_voice_call_incoming.visibility = View.GONE
        sky_voice_call_timeout.visibility = View.GONE
        sky_voice_call_timer.visibility = View.GONE
        cancelTimer()
    }

    //呼叫取消
    private fun cancelCall() {
        cancelTimer()
        Constant.CALL_STATE = Constant.CALL_STANDBY
        callEnd(false)
    }

    private fun showCalling(audioOnly: Boolean) {
        if (callEnded) {
            return
        }

        if (audioOnly) {
            //移除视频画面
            ll_voice_call.visibility = View.VISIBLE
        } else {
            //显示视频画面
            fullscreen_video_frame.visibility = View.VISIBLE
            pip_video_frame.visibility = View.VISIBLE
            ll_voice_call.visibility = View.GONE
        }

        Constant.CALL_STATE = Constant.CALL_CALLING
        sky_voice_call_calling_text.text = StringUtil.getResString(R.string.call_in_call)
        sky_voice_call_timeout.visibility = View.GONE
        cancelTimer()
        sky_voice_call_timer.visibility = View.VISIBLE
        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
        sky_voice_call_timer.start()
    }

    //通话结束
    override fun callEnd(handoff: Boolean) {
        synchronized(this) {
            if (callEnded) {
                return
            }
            callEnded = true
            Constant.CALL_STATE = Constant.CALL_STANDBY
            if (sky_voice_call_timer != null) {
                sky_voice_call_timer.stop()
            }

            Log.e(TAG, "call end !!!!!!!!!!!!!!!!!!")
            if (handoff) {
                if (visiting) {
                    VideoUtil.handoffVideoCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
                } else {
                    VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
                }
            }

            if (janusClient!!.webSocketChannel != null) {
                janusClient!!.callState = EnumType.CallState.Idle
                if (callState == 0) {
                    janusClient!!.destroyRoom(janusClient!!.currentHandleId, null)
                } else {
                    janusClient!!.leaveRoom()
                }

                janusClient!!.disConnect()
            }

            backToMain()
        }
    }

    //探视
/*    private fun startVisiting(targetId: String) {
        //如果设备没有摄像头则只能语音通话
        if (!startCall(targetId, !Constant.supportCamera)) {
            //通话失败，重置并返回主界面
            Constant.CALL_STATE = Constant.CALL_STANDBY
            VideoUtil.rejectVideoCall(Constant.DEVICE_ID, fromId, interactionVO!!.id)
            if (sky_voice_call_timer != null) {
                sky_voice_call_timer.stop()
            }
            backToMain()
        }
    }*/


    /********************************************************
     ********************* 通话回调 ********************
     * 注意: 如涉及到UI更新的需要在主线程处理，务必注意
     ********************************************************/
    override fun didChangeState(var1: EnumType.CallState?) {
        if (var1 == EnumType.CallState.Connected) {
            handler.post {
                RingPlayHelper.stopRingTone()
                //更新界面显示
                showCalling(audioCall)
            }
        }
    }

    override fun didDisconnected(userId: String?) {
        Log.i(TAG, "disconnected user:" + userId + ",call user:" + Constant.TARGET_SIP)
        if (userId.equals(Constant.TARGET_SIP)) {
            Log.w(TAG, "didDisconnected: $userId")
            handler.post {
                showMessage("$userId disconnect")
                callEnd(true)
            }
        }
    }

    override fun didCreateLocalVideoTrack() {

    }

    override fun didError(error: String?) {
        Log.e(TAG, "didError: $error")
        handler.post {
            showMessage(R.string.call_error)
            callEnd(true)
        }
    }

    override fun didHangUp(handlerId: BigInteger) {
        Log.e("hangup", "socket hangup")
        handler.post {
            callEnd(true)
        }
    }

    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
        // TODO("Not yet implemented")
    }


    override fun didCallEndWithReason(var1: EnumType.CallEndReason?) {
        handler.post {
            callEnd(true)
        }
    }

    override fun didChangeMode(isAudioOnly: Boolean) {

    }

    override fun didUserLeave(userId: BigInteger?) {
        Log.w(TAG, "didUserLeave:"+userId)
        handler.post {
            callEnd(true)
        }
    }



    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onMoonEvent(messageEvent: MessageEvent) {
        when (messageEvent.type) {
            Constant.EVENT_TCP_MSG -> {
                if (messageEvent.message is TcpModel) {
                    val curTcpModel = messageEvent.message as TcpModel
                    if (curTcpModel.getType() == TcpType.VOICE) {
                        if (curTcpModel.action == TcpAction.VoiceAction.CANCEL_BY_DOOR) {
                            Constant.CALL_STATE = Constant.CALL_STANDBY
                            VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
                            cancelCall()
                            return
                        }

                        if (curTcpModel.data != null) {
                            val curInteractionVO = Gson().fromJson(curTcpModel.data.toString(), InteractionVO::class.java)
                            if (curTcpModel.getAction() == TcpAction.VoiceAction.ACCEPT) {
                                //我方呼出，对方接受
                                RingPlayHelper.stopRingTone()
                                Constant.interactionId = curInteractionVO.id
                                fromId = curTcpModel.fromId
                                acceptCall()
                                if (TextUtils.isEmpty(curInteractionVO.toSipId)) {
                                    //通话失败，重置并返回主界面
                                    showMessage("targetSipId empty!")
                                    Constant.CALL_STATE = Constant.CALL_STANDBY
                                    callEnd(true)
                                }
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.REJECT) {
                                //我方呼出，对方拒绝
                                showMessage(R.string.call_reject)
                                RingPlayHelper.stopRingTone()
                                cancelCall()
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.CALLING) {
                                //我方呼出，对方通话中
                                showMessage(R.string.call_busy)
                                /*AppTool.Time.delay(1000) {
                                RingPlayHelper.stopRingTone()
                                cancelCall()
                            }*/
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.SUCCESS) {
                                //呼叫成功
                                //本机呼叫的时候tcpModel为空，只有呼叫成功的时候才能获得对应tcp相关数据
                                callSuccess = true
                                sky_voice_call_hangup.isEnabled = true
                                interactionVO = curInteractionVO
                                Constant.interactionId = curInteractionVO.id
                                showOutgoingCall()
                                janusClient!!.connect()
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.FAILED) {
                                //我方呼出，对方不在线，设备离线或其它错误
                                callSuccess = true
                                showMessage(R.string.call_failed)
                                AppTool.Time.delay(1500) {
                                    RingPlayHelper.stopRingTone()
                                    cancelCall()
                                }
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.HANDOFF) {
                                //对方挂断，不论我方呼出或呼入
                                if (Constant.interactionId == curInteractionVO.id) {
                                    RingPlayHelper.stopRingTone()
                                    cancelCall()
                                }
                            } else if (curTcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
                                //对方呼叫时取消
                                if (Constant.interactionId == curInteractionVO.id) {
                                    RingPlayHelper.stopRingTone()
                                    cancelCall()
                                }
                            }
                        }
                    }
                }
            }

            //外部呼叫按键
            Constant.EVENT_SERIAL_EVENT -> {
                if (messageEvent.message is String) {
                    val serialAction = messageEvent.message as String
                    if (serialAction.equals("cancel")) {
                        RingPlayHelper.stopRingTone()
                        Constant.CALL_STATE = Constant.CALL_STANDBY
                        VoiceUtil.cancelAudioCall(Constant.DEVICE_ID)
                        cancelCall()
                    } else if (serialAction.equals("accept")) {
                        RingPlayHelper.stopRingTone()
                        Constant.CALL_STATE = Constant.CALL_CALLING
                        VoiceUtil.acceptAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
                        acceptCall()
                        janusClient!!.connect()
                    } else if (serialAction.equals("handoff")) {
                        Constant.CALL_STATE = Constant.CALL_STANDBY
                        callEnd(true)
                    } else if (serialAction.equals("reject")) {
                        RingPlayHelper.stopRingTone()
                        Constant.CALL_STATE = Constant.CALL_STANDBY
                        VoiceUtil.rejectAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
                        callEnd(false)
                    }
                }
            }
        }
    }

}