package com.cr.pages

import android.os.Bundle
import android.view.LayoutInflater
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.activityViewModels
import com.cr.cruav.R
import com.cr.viewmodel.CrFlightControlVM
import com.cr.viewmodel.CrVideoChannelListener
import com.cr.viewmodel.CrVideoChannelVM
import dji.v5.common.video.channel.VideoChannelType
import dji.v5.common.video.decoder.DecoderOutputMode
import dji.v5.common.video.decoder.DecoderState
import dji.v5.common.video.decoder.VideoDecoder
import dji.v5.common.video.interfaces.DecoderStateChangeListener
import dji.v5.common.video.interfaces.IVideoChannel
import dji.v5.common.video.interfaces.IVideoDecoder


/**
 * 操作系统：MAC系统
 * 创建者：王成
 * 创建日期：2023/3/10 08:50
 * 描述：图传窗口
 */
class FragmentFPV : CrAnimationFragment(), SurfaceHolder.Callback {
    /**
     * FPV窗口监听
     */
    interface FPVListener{
        // todo: 2023/3/13 切换窗口
        fun triggerWindow()
    }
    // define: 2023/3/10 延迟初始化一个通道模型
    private val videoChannelVM: CrVideoChannelVM by activityViewModels()

    // define: 2023/3/10 将飞行器视图绑定到模型
    private val flightControlVm: CrFlightControlVM by activityViewModels()

    // define: 2023/3/10 延迟初始化一个视频画布
    private lateinit var surfaceView: SurfaceView
    private var btnTrigger: Button? = null

    // define: 2023/3/11 视频通道
    private var curVideoChannel: IVideoChannel? = null

    // define: 2023/3/10 定义视频解码器
    private var videoDecoder: IVideoDecoder? = null

    // todo: 2023/3/13 监听
    lateinit var listener:FPVListener

    /**
     * 创建视图
     * @param inflater LayoutInflater
     * @param container ViewGroup?
     * @param savedInstanceState Bundle?
     * @return View?
     */
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        var view = inflater.inflate(R.layout.frag_fpv, container, false)
        // todo: 2023/3/13 给View挂接事件
        view.setOnClickListener(clickListener)
        // todo: 2023/3/10 挂接图传视图控件
        surfaceView = view.findViewById(R.id.surface_fpv)
        btnTrigger = view.findViewById(R.id.fpv_trigger)
        btnTrigger?.setOnClickListener(clickListener)
        // todo: 2023/3/10 设置视图控件监听
        surfaceView.holder.addCallback(this)
        return view
    }

    /**
     * 视图创建完成后调用
     * @param view View
     * @param savedInstanceState Bundle?
     */
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // todo: 2023/3/11 初始化
        init()
    }

    /**
     * 点击事件
     */
    private var clickListener = View.OnClickListener {
        when(it.id){
            R.id.fpv_trigger -> {
                // todo: 2023/3/13 切换视频通道
                videoChannelVM.triggerStreamSource()
            }
            R.id.fpv_layout ->{
                // todo: 2023/3/13 切换窗口
                listener?.triggerWindow()
            }
        }
    }

    /**
     * 初始化
     */
    private fun init() {
        // todo: 2023/3/11 绑定视频通道变化监听
        videoChannelVM.listener = object : CrVideoChannelListener {
            // todo: 2023/3/13 变更通道
            override fun initVideoChannel(videoChannel: IVideoChannel) {
                curVideoChannel = videoChannel
                setChannelToSurface()
            }

            // todo: 2023/3/13 更新通道类型
            override fun updateVideoChannelType(channelType: VideoChannelType) {
                changeVideoDecoder(channelType)
            }
        }
        // todo: 2023/3/11 订阅飞行器
        flightControlVm.flightControlInfo.observe(requireActivity()) {
            it?.let {
                if (it.isConnection) {
                    videoChannelVM.beginVideoChannel()
                } else {
                    videoChannelVM.endVideoChannel()
                }
            }
        }
    }

    /**
     * 变更通道类型
     * @param channelType VideoChannelType
     */
    private fun changeVideoDecoder(channelType:VideoChannelType){
        videoDecoder?.videoChannelType = channelType
        surfaceView.invalidate()
    }

    /**
     * 设置视频通道到画布
     */
    private fun setChannelToSurface() {
        if (videoDecoder == null) {
            curVideoChannel?.let {
                videoDecoder = VideoDecoder(
                    this@FragmentFPV.context,
                    it.videoChannelType,
                    DecoderOutputMode.SURFACE_MODE,
                    surfaceView.holder
                )
                // todo: 2023/3/10 添加解码状态监听
                videoDecoder?.addDecoderStateChangeListener(decoderStateChangeListener)
            }
        } else if (videoDecoder?.decoderStatus == DecoderState.PAUSED) {
            videoDecoder?.onResume()
        }
    }

    /**
     * 编码状态监听
     */
    private val decoderStateChangeListener =
        DecoderStateChangeListener { oldState, newState ->
            mainHandler.post {
                // todo: 2023/3/10 更新编码状态
                videoChannelVM.videoChannelInfo.value?.decoderState = newState
                // todo: 2023/3/10 刷新数据
                videoChannelVM.refresh(videoChannelVM.videoChannelInfo)
            }
        }

    /**
     * surfaceView 创建监听
     * @param p0 SurfaceHolder
     */
    override fun surfaceCreated(p0: SurfaceHolder) {
        setChannelToSurface()
    }

    /**
     * surfaceView变化监听
     * @param p0 SurfaceHolder
     * @param p1 Int
     * @param p2 Int
     * @param p3 Int
     */
    override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
        setChannelToSurface()
    }

    /**
     * surfaceView释放监听
     * @param p0 SurfaceHolder
     */
    override fun surfaceDestroyed(p0: SurfaceHolder) {
        // todo: 2023/3/10 停止解码
        videoDecoder?.onPause()
    }

    /**
     * 覆写视图释放
     */
    override fun onDestroyView() {
        super.onDestroyView()
        // todo: 2023/3/10 释放编码资源
        if (videoDecoder != null) {
            videoDecoder?.destroy()
            videoDecoder = null
        }
    }
}