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

import java.util.List;

import cn.tee3.avd.AVDRecord.RecordAudioType;
import cn.tee3.avd.AVDRecord.RecordVideoType;

/**
 * 直播频道管理接口.
 *
 * 直播频道管理定义引擎中直播频道的创建、删除、信息获取和频道控制等功能。
 * 直播频道：类似电视频道，能够承载一路视频和音频的一个逻辑通道；直播源通过直播频道发布视频，直播播放端通过直播频道订阅和观看直播音视频。
 */
public class AVDLive {
    private static final String TAG = "AVDLive";
    /** 获取AVDLive接口对象
     *
     * @note AVDLive，一个进程空间只存在一个直播接口。
     * @return 返回AVDLive。
     */
    public static AVDLive instance() {
        return SingletonHolder.INSTANCE;
    }

    /** 直播状态定义 */
    public static enum LiveStatus {
        ls_created,							/**< 创建直播 */
        ls_living,							/**< 正在直播 */
        ls_stopped,							/**< 直播暂停  */
        ls_removed,							/**< 直播被删除  */
        ls_exception,						/**< 直播异常 */
    }

    /**
     * 直播频道数据结构.
     *
     * 直播频道数据定义了一个直播频道的基本信息。
     */
    public static class LiveInfo {
        String id;						/**< 频道的ID */
        String name;					/**< 直播频道的名称 */
        String description;				/**< 直播频道描述 */
        String tags;					/**< 直播标记 */
        String userId;					/**< 用户号，可不存在，存在时与audioType，videoType一起使用；直播此用户的相关音频和视频数据 */
        RecordAudioType audioType;		/**< 音频类型 */
        RecordVideoType videoType;		/**< 视频类型 */
        String createTime;				/**< 频道创建起始时间 */
        long   duration;				/**< 频道从创建到现在的时长 */
        String playerPassword;			/**< 播放密码 */
        String roomId;					/**< 频道关联房间号 */
        LiveStatus status;				/**< 直播状态 */
        String publishurl;				/**< 推流地址，创建时可带上，若存在，服务器优先推送此地址 */
        String rtmpurl;					/**< 播放rtmp链接 */
        String hlsurl;					/**< 播放hls链接 */

        public LiveInfo() {
            id = "";
            name = "";
            description = "";
            tags = "";
            userId = "";
            audioType = RecordAudioType.ra_none;
            videoType = RecordVideoType.rv_none;
            createTime = "";
            duration = 0;
            status = LiveStatus.ls_created;
            roomId = "";
            publishurl = "";
            rtmpurl = "";
            hlsurl = "";
        }
        protected LiveInfo(RecordAudioType at, RecordVideoType vt, LiveStatus status, int duration,
                           String id, String name, String description, String tags, String userId, String createTime, String roomId, String puburl, String rtmpurl, String hlsurl) {
            this.audioType = at;
            this.videoType = vt;
            this.duration = duration;
            this.id = id;
            this.status = status;
            this.name = name;
            this.description = description;
            this.tags = tags;
            this.userId = userId;
            this.createTime = createTime;
            this.roomId = roomId;
            this.publishurl = puburl;
            this.rtmpurl = rtmpurl;
            this.hlsurl = hlsurl;
        }

        public String getId() { return this.id; }
        public String getName() { return this.name; }
        public void setName(String value) { this.name = value; }
        public String getDescription() { return this.description; }
        public void setDescription(String value) { this.description = value; }
        public String getTags() { return this.tags; }
        public void setTags(String value) { tags = value; }
        public String getUserId() { return this.userId; }
        public void setUserId(String value) { this.userId = value; }
        public String getFileType() { return this.playerPassword; }
        public RecordAudioType getAudioType() { return this.audioType; }
        public int getAudioTypeValue() { return this.audioType.ordinal(); }
        public void setAudioType(RecordAudioType value) { this.audioType = value; }
        public RecordVideoType getVideoType() { return this.videoType; }
        public int getVideoTypeValue() { return this.videoType.ordinal(); }
        public void setVideoType(RecordVideoType value) { this.videoType = value; }
        public String getPublishurl() { return this.publishurl; }
        public void setPublishurl(String value) { this.publishurl = value; }
        public String getRtmpurl() { return this.rtmpurl; }
        public void setRtmphurl(String value) { this.rtmpurl = value; }
        public String getHlsurl() { return this.hlsurl; }
        public void setHlsurl(String value) { this.hlsurl = value; }
        public String getCreateTime() { return this.createTime; }
        public long getDuration() { return this.duration; }
        public LiveStatus getStatus() { return this.status; }
        public String getRoomId() { return this.roomId; }
        public void setRoomId(String value) { this.roomId = value; }

        @Override
        public boolean equals(Object obj) {
            LiveInfo objd = (LiveInfo) obj;
            if (null == objd) {
                return false;
            }
            return objd.getId().equals(this.getId());
        }
        @Override
        public String toString() {
            return "LiveInfo: id=" + this.id + ",name="+this.name + ",userId="+this.userId+",audio="+this.audioType+",video="+this.videoType+",status="+this.status;
        }
        public boolean isValid() {
            return (null != id && !id.isEmpty());
        }
    }



    /**
     * 直播回调接口类
     *
     * 直播回调接口定义了直播管理操作的异步返回。
     */
    public static interface Listener {
        /** 创建特定用户直播的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] info 直播信息。
         *
         * @sa createUserLive
         */
        public void onCreateUserLive(int result, LiveInfo info);
        /** 停止特定直播的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] liveId 直播号。
         *
         * @sa stopLive
         */
        public void onStopLive(int result, String liveId);

        ///
        /** 获取特定直播详细信息的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] info 直播信息。
         *
         * @sa getLiveInfo
         */
        public void onLiveInfo(int result, LiveInfo info);
        /** 获取服务器上直播列表的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] total  总共直播数。
         * @param[in] begin  当前起始序号。
         * @param[in] items 直播信息集合。
         *
         * @sa getWorkingLives
         */
        public void onLiveInfos(int result, int total, int begin, List<LiveInfo> items);
        /** 删除特定直播的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] liveId 直播号。
         *
         * @sa deleteLive
         */
        public void onDeleteLive(int result, String liveId);
    }

    ///
    private long nativeobj = 0;
    private long nativeListener = 0;
    private Listener listener4cb = null;
    private Handler listenerHandler = null;
    private SDKListener listener4native = null;
    ///
    private static class SingletonHolder {
        static final AVDLive INSTANCE = new AVDLive();
    }
    private AVDLive() {
        nativeobj = nativegetAVDLive();
        if (0 == nativeobj) {
            throw new RuntimeException("Failed to Create AVDLive!");
        }
    }

     protected void initWithCB(Listener cb) {
        this.listener4cb = cb;
        if (0 == this.nativeListener) {
            initHandler();
            this.nativeListener = nativeCreateListener(listener4native);
            Tlog.d(TAG, "initWithCB, Create nativelistener:" + nativeListener);
        }
    }
    protected void dispose() {
        if (0 != this.nativeListener) {
            nativeFreeListener(this.nativeListener);
            this.nativeListener = 0;
        }
        this.listener4cb = null;
        this.listenerHandler = null;
        this.listener4native = null;
    }

    /** 设置房间聊天模块回调接口
     *
     * @param[in] listener 聊天模块回调接口指针。
     * @return 返回错误代码。
     * @sa Listener
     */
    public boolean setListener(Listener listener) {
        Tlog.d(TAG, "setListener, listener:" +listener+",listener4native="+this.listener4native+",listenerHandler="+this.listenerHandler);
        if (null == listener) {
            dispose();
        }
        else {
            initWithCB(listener);
        }
        Tlog.v(TAG, "setListener, out:");
        return true;
    }

    /** 创建特定用户直播
     *
     * @param[in] info 中roomId，name, userid, fileType必须设置；创建成功时id会设置成新创建的直播Id，在异步返回中返回。
     * @return 返回错误代码。
     * @note 参数结构中的音频类型缺省为：ra_user_single
    视频类型缺省为：rv_main
     *		为异步操作，操作结果在 onCreateUserLive 中返回。
     * @sa onCreateUserLive
     */
    public int createUserLive(LiveInfo info) {
        Tlog.d(TAG, "createUserLive, info:" + info.toString());
        return nativecreateUserLive(info);
    }
    /** 停止特定直播
     *
     * @param[in] liveId 直播号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onStopLive 中返回。
     * @sa onStopLive
     */
    public int stopLive(String liveId) {
        Tlog.d(TAG, "stopLive, liveId:" + liveId);
        if (null == liveId || liveId.isEmpty()) {
            Tlog.e(TAG, "stopLive, invalid liveId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativestopLive(liveId);
    }
    /** 获取特定直播详细信息
     *
     * @param[in] liveId 直播号。
     * @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);
    }
    /** 获取服务器上的直播列表
     *
     * @param[in] begindex 分页的起始索引。
     * @param[in] ncount 分页的请求数量。
     * @param[in] filter 查询条件，以json表示，如：{ "roomId":"hafds2324" }。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onLiveInfos 中返回。
     * @sa onLiveInfos
     */
    public int findLiveInfos(int begindex, int ncount, String filter) {
        Tlog.d(TAG, "findLiveInfos, begindex:" + begindex+",ncount:"+ncount+",filter:"+filter);
        return nativefindLiveInfos(begindex, ncount, filter);
    }
    /** 删除特定直播
     *
     * @param[in] liveId 直播号。
     * @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 static native long nativegetAVDLive();
    private native long nativeCreateListener(Listener listener);
    private native void nativeFreeListener(long nativeListener);
    private native int nativecreateUserLive(LiveInfo info);
    private native int nativestopLive(String liveId);
    private native int nativegetLiveInfo(String liveId);
    private native int nativefindLiveInfos(int begindex, int ncount, String filter);
    private native int nativedeleteLive(String liveId);
    ///
    private static final int msg_onCreateUserLive = 1;
    private static final int msg_onStopLive = 2;
    private static final int msg_onLiveInfo = 3;
    private static final int msg_onLiveInfos = 4;
    private static final int msg_onDeleteLive = 5;

    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() {
            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_onCreateUserLive:
                        listener4cb.onCreateUserLive(msg.arg1, (LiveInfo) msg.obj);
                        break;
                    case msg_onStopLive:
                        listener4cb.onStopLive(msg.arg1, (String) msg.obj);
                        break;
                    case msg_onLiveInfo:
                        listener4cb.onLiveInfo(msg.arg1, (LiveInfo) msg.obj);
                        break;
                    case msg_onLiveInfos:
                        listener4cb.onLiveInfos(msg.arg1, 0, 0, (List<LiveInfo>) 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 onCreateUserLive(int result, LiveInfo info) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onCreateUserLive, result,0,info);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onStopLive(int result, String liveId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onStopLive, result,0,liveId);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onLiveInfo(int result, 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 onLiveInfos(int result, int total, int begin, List<LiveInfo> items) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onLiveInfos,  result,0,items);
            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);
        }
    }
}
