package cn.tee3.avd;
/**
 * Created by bob.liu on 2016/4/24.
 */
import android.os.Handler;
import android.os.Looper;

import java.util.List;

/**
 * 房间旁路直播管理接口.
 *
 * 房间旁路直播定义房间中直播频道的创建、删除、信息获取和频道控制等功能。
 * 直播频道：类似电视频道，能够承载一路视频或一路混流视频和音频的一个逻辑通道；直播源通过直播频道发布视频，直播播放端通过直播频道订阅和观看直播音视频。
 */
public class MSvrLive extends Module {
    private static final String TAG = "MSvrLive";
    /**
     * 直播频道回调接口类
     *
     * 直播频道回调接口定义了直播频道管理操作的异步返回。
     */
    public static interface Listener {
        /// 异步返回
        /** 创建直播频道的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] info 直播频道信息。
         *
         * @sa createLive
         */
        public void onCreateLive(int result, AVDLive.LiveInfo info);
        /** 为特定直播频道设置当前视频源的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] lvbc_id 频道号。
         * @param[in] selectedVideo 已发布的视频Id。
         *
         * @sa selectMedia4Live
         */
        public void onSelectMedia4Live(int result, String lvbc_id);
        /** 为特定直播频道设置混流视频源的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] lvbc_id 频道号。
         * @sa selectMedia4Live
         */
        public void onMixMedia4Live(int result, String lvbc_id);
        /** 停止特定直播频道的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] lvbc_id 频道号。
         *
         * @sa pauseResumeLive
         */
        public void onPauseResumeLive(int result, String lvbc_id);
        /** 获取特定频道详细信息的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] info 直播频道信息。
         *
         * @sa getLiveInfo
         */
        public void onLiveInfo(int result, AVDLive.LiveInfo info);
        /** 删除特定频道的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] lvbc_id 频道号。
         *
         * @sa deleteLive
         */
        public void onDeleteLive(int result, String lvbc_id);
    }

    public static class VideoItem {
        String id;                   //摄像头Id，唯一标示一路共享的摄像头视频。
        float x, y;                 //此视频在左上角左边位置（上边位置），即x坐标，取值0.0~1.0，内部取值为：width * X（height * Y）
        float width, height;       //此视频宽度（高度）比例，取值0.0~1.0，内部取值为：width * W（height * H）
        int zorder;                 //多个视频覆盖时，前后位置，zorder越小，视频越在下层，会被覆盖；取值0-10
        int alpha;                  //（暂不使用）透明度
        VideoRenderer.ScalingType render; //（暂不使用）视频渲染到混流视频上的渲染模式

        VideoItem() {
            x = y = width = height = 0.0f;
            zorder = alpha = 0;
            render = VideoRenderer.ScalingType.Scale_Aspect_Fit;
        }
        VideoItem(String aId, float ax, float ay, float aw, float ah, int az) {
            id = aId;
            x = ax;
            y = ay;
            width = aw;
            height = ah;
            zorder = az;
        }

        public String getId() { return this.id; }
        public void setId(String value) { this.id = id; }

        public float getX() { return this.x; }
        public void setX(float value) { this.x = value; }
        public float getY() { return this.y; }
        public void setY(float value) { this.y = value; }
        public float getWidth() { return this.width; }
        public void setWidth(float value) { this.width = value; }
        public float getHeight() { return this.height; }
        public void setHeight(float value) { this.height = value; }

        public int getZorder() { return this.zorder; }
        public void setZorder(int value) { this.zorder = value; }
        public int getAlpha() { return this.alpha; }
        public void setAlpha(int value) { this.alpha = value; }

        public VideoRenderer.ScalingType getRenderType() { return this.render; }

        @Override
        public String toString() {
            return "video--id:" + this.id + " x:"+this.x + " y:"+this.y + " w:"+this.width+" h:"+this.height+" z:"+this.zorder+" r:"+this.render;
        }
    }
    /**
     * 视频混流信息结构.
     *
     * 视频混流信息结构定义了一个视频混流的基本信息。
     */
    public static class MixVideos {
        int mixWidth;				//混流输出视频分辨率宽
        int mixHeight;				//混流输出视频分辨率高
        int backgroundColor;		//如："#C0C0C0" RGB
        int outBitrate;			//混流输出码率
        int outFps;				//混流输出帧率
        List<VideoItem> videos;    //混流的视频列表

        public MixVideos() {
            mixWidth = mixHeight = 0;
            backgroundColor = 0;
            outBitrate = 0;
            outFps = 0;
        }
        public MixVideos(int aw, int ah, int outbt) {
            mixWidth = aw;
            mixHeight = ah;
            outBitrate = outbt;
            backgroundColor = 0;
            outFps = 0;
        }

        public int getMixWidth() { return this.mixWidth; }
        public void setMixWidth(int value) { this.mixWidth = value; }
        public int getMixHeight() { return this.mixHeight; }
        public void setMixHeight(int value) { this.mixHeight = value; }
        public int getBackgroundColor() { return this.backgroundColor; }
        public void setBackgroundColor(int value) { this.backgroundColor = value; }
        public int getOutBitrate() { return this.outBitrate; }
        public void setOutBitrate(int value) { this.outBitrate = value; }
        public int getOutFps() { return this.outFps; }
        public void setOutFps(int value) { this.outFps = value; }
        public List<VideoItem> getVideos() { return this.videos; }

        @Override
        public String toString() {
            StringBuffer builder = new StringBuffer("MixVideos mw:" + this.mixWidth + ",mh:"+this.mixHeight + ",clr:"+this.backgroundColor + ",bps:"+this.outBitrate+",fps:"+this.outFps);
            builder.append(" videos: ");
            for (VideoItem item : this.videos) {
                String items = item.toString();
                builder.append(items);
            }
            return builder.toString();
        }
    };

    ///
    private long nativeListener = 0;
    private Listener listener4cb = null;
    private Handler listenerHandler = null;
    private SDKListener listener4native = null;
    ///
    /** 获取引擎的直播功能接口
     *
     * @return 返回直播接口。
     */
    public static MSvrLive getSvrLive(Room room) {
        return (MSvrLive)room.getModule(Type.svrlive);
    }
    protected MSvrLive(Room room) {
        super(room, Type.chat, room.nativegetMSvrLive());
        Tlog.d(TAG, "MSvrLive, nativeSvrLive:" + this.nativeobj);
        setListener(null);
    }
    @Override
    protected void dispose() {
        if (0 != this.nativeListener) {
            nativeFreeListener(this.nativeListener);
        }
        this.nativeListener = 0;
        this.nativeobj = 0;
    }

    /** 设置直播功能回调
     *
     * @param[in] *listener 回调指针。
     * @return 返回错误代码。
     */
    public boolean setListener(Listener listener) {
        Tlog.d(TAG, "setListener, listener:" +listener+",listener4native="+this.listener4native+",listenerHandler="+this.listenerHandler);
        this.listener4cb = listener;
        if (0 == this.nativeListener) {
            initHandler();
            this.nativeListener = nativeCreateListener(listener4native);
            Tlog.d(TAG, "setListener, Create nativelistener:" + nativeListener);
        }
        Tlog.v(TAG, "setListener, out:");
        return true;
    }
    private native long nativeCreateListener(Listener listener);
    private native void nativeFreeListener(long nativeListener);

    /** 创建直播频道
     *
     * @param[in,out] info 中roomId，name必须设置；创建成功时id会设置成新创建的直播频道Id。
     * @note 为异步操作，操作结果在 onCreateLive 中返回。
     * @sa onCreateLive
     */
    public int createLive(AVDLive.LiveInfo info) {
        Tlog.d(TAG, "createLive, info:" + info.toString());
        return nativecreateLive(info);
    }
    private native int nativecreateLive(AVDLive.LiveInfo info);

    /** 为特定直播频道设置当前视频源
     *
     * @param[in]  lvbc_id 频道号。
     * @param[in]  selectedVideo 已发布的视频Id,直播的视频源。
     * @param[in]  audioUserId 直播的音频用户Id，可选房间中所有用户音频 AVD_userId_allUser。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onSelectVideo4Live 中返回。
     * 函数调用后，服务器立即开启单路视频流推流模式。与接口mixMedia4Live相互影响，以最后一个调用为当前旁路直播的媒体源。
     * @sa onSelectMedia4Live
     * @sa AVD_userId_allUser
     */
    public int selectMedia4Live(String lvbc_id, String selectedVideo, String audioUserId) {
        Tlog.d(TAG, "selectMedia4Live, lvbc_id:" +lvbc_id+",selectedVideo:"+selectedVideo+",audioUserId:"+audioUserId);
        return nativeselectMedia4Live(lvbc_id,selectedVideo,audioUserId);
    }
    private native int nativeselectMedia4Live(String lvbc_id, String selectedVideo, String audioUserId);
    /** 为特定直播频道设置混流视频源
     *
     * @param[in]  lvbc_id 频道号。
     * @param[in]  mixs 混流视频源信息结构。
     * @param[in]  audioUserId 直播的音频用户Id，可选房间中所有用户音频 AVD_userId_allUser。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onMixMedia4Live 中返回。
     * 函数调用后，服务器立即开启混流推流模式。与接口selectMedia4Live相互影响，以最后一个调用为当前旁路直播的媒体源。
     * @sa onMixMedia4Live
     * @sa AVD_userId_allUser
     */
    public int mixMedia4Live(String lvbc_id, MixVideos mixs, String audioUserId) {
        Tlog.d(TAG, "mixMedia4Live, lvbc_id:" +lvbc_id+",mixs:"+mixs.toString()+",audioUserId:"+audioUserId);
        return nativemixMedia4Live(lvbc_id,mixs,audioUserId);
    }
    private native int nativemixMedia4Live(String lvbc_id, MixVideos mixs, String audioUserId);
    /** 恢复和暂停特定直播频道
     *
     * @param[in]  lvbc_id 频道号。
     * @param[in]  isResume 是否恢复。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onPauseResumeLive 中返回。
     * @sa onPauseResumeLive
     */
    public int pauseResumeLive(String liveId, boolean isResume) {
        Tlog.d(TAG, "pauseResumeLive, liveId:" + liveId + ",isResume:" +isResume);
        if (null == liveId || liveId.isEmpty()) {
            Tlog.e(TAG, "pauseResumeLive, invalid liveId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativepauseResumeLive(liveId, isResume);
    }
    private native int nativepauseResumeLive(String liveId, boolean isResume);
    /** 获取特定频道详细信息
     *
     * @param[in]  lvbc_id 频道号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onLiveInfo 中返回。
     * @sa onLiveInfo
     */
    public int getLiveInfo(String liveId) {
        Tlog.d(TAG, "getLiveInfo, liveId:" + liveId);
        if (null == liveId || liveId.isEmpty()) {
            Tlog.e(TAG, "getLiveInfo, invalid liveId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativegetLiveInfo(liveId);
    }
    private native int nativegetLiveInfo(String liveId);
    /** 删除特定频道
     *
     * @param[in]  lvbc_id 频道号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onDeleteLive 中返回。
     * @sa onDeleteLive
     */
    public int deleteLive(String liveId) {
        Tlog.d(TAG, "deleteLive, liveId:" + liveId);
       if (null == liveId || liveId.isEmpty()) {
           Tlog.e(TAG, "deleteLive, invalid liveId.");
           return ErrorCode.Err_Invalid_Arg;
       }
        return nativedeleteLive(liveId);
    }
    private native int nativedeleteLive(String liveId);
    ///
    private static final int msg_onCreateLive = 1;
    private static final int msg_onSelectMedia4Live = 2;
    private static final int msg_onMixMedia4Live = 3;
    private static final int msg_onPauseResumeLive = 4;
    private static final int msg_onLiveInfo = 5;
    private static final int msg_onDeleteLive = 6;

    private boolean initHandler() {
        if (null == listener4native) {
            listener4native = new SDKListener();
        }
        if (null != listenerHandler) {
            return true;
        }
        AVDEngine.runOnLoopThreadSync(new Runnable() {
            @Override
            public void run() {
                initHandler_main();
            }
        });
        return true;
    }
    private boolean initHandler_main() {
        this.listenerHandler = new Handler(Looper.getMainLooper()) {
            public void handleMessage(android.os.Message msg) {
                Tlog.v(TAG, "handleMessage, msg:" + msg.toString());
                if (null == listener4cb) {
                    super.handleMessage(msg);
                    return;
                }
                switch (msg.what) {
                    case msg_onCreateLive:
                        listener4cb.onCreateLive(msg.arg1, (AVDLive.LiveInfo) msg.obj);
                        break;
                    case msg_onPauseResumeLive:
                        listener4cb.onPauseResumeLive(msg.arg1, (String) msg.obj);
                        break;
                    case msg_onLiveInfo:
                        listener4cb.onLiveInfo(msg.arg1, (AVDLive.LiveInfo) msg.obj);
                        break;
                    case msg_onSelectMedia4Live:
                        listener4cb.onSelectMedia4Live(msg.arg1, (String) msg.obj);
                        break;
                    case msg_onMixMedia4Live:
                        listener4cb.onMixMedia4Live(msg.arg1, (String) msg.obj);
                        break;
                    case msg_onDeleteLive:
                        listener4cb.onDeleteLive(msg.arg1, (String) msg.obj);
                        break;
                }
                super.handleMessage(msg);
            }
        };
        return true;
    }
    private class SDKListener implements Listener {
        public SDKListener() {
        }
        @Override
        public void onCreateLive(int result, AVDLive.LiveInfo info) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onCreateLive, result,0,info);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onPauseResumeLive(int result, String liveId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onPauseResumeLive, result,0,liveId);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onLiveInfo(int result, AVDLive.LiveInfo info) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onLiveInfo,  result,0,info);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onDeleteLive(int result, String liveId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onDeleteLive,  result,0,liveId);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onSelectMedia4Live(int result, String liveId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onSelectMedia4Live,  result,0,liveId);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onMixMedia4Live(int result, String liveId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onMixMedia4Live,  result,0,liveId);
            listenerHandler.sendMessage(msg);
        }
    }
}
