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

import java.util.LinkedList;
import java.util.List;

/**
 * 录制管理接口.
 *
 * 录制管理定义引擎中录制的创建、删除、信息获取和录制控制等功能。
 */
public class AVDRecord {
    private static final String TAG = "AVDRecord";
    /** 获取AVDRecord接口对象
     *
     * @note AVDRecord是一个单例对象，一个进程空间只存在一个录制接口。
     * @return 返回AVDRecord。
     */
    public static AVDRecord instance() {
        return SingletonHolder.INSTANCE;
    }

    /** 录制音频类型定义 */
    public static enum RecordAudioType{
        ra_none,							/**< 无音频  */
        ra_user_single,						/**< 同视频用户的单用户音频  */
        ra_user_all,						/**< 整个房间中的所有音频混音  */
    }
    /** 录制视频类型定义 */
    public static enum RecordVideoType {
        rv_none,							/**< 无视频  */
        rv_main,							/**< 视频主流  */
        rv_ass1,							/**< 视频辅流1  */
        rv_ass2,							/**< 视频辅流2  */
    }
    /** 媒体文件类型定义 */
    public static enum MediaFileType {
        mt_mp4,								/**< MP4 文件格式，支持h264视频和aac音频封装  */
        mt_webm,							/**< WebM文件格式，支持vp8视频和opus音频封装  */
    }
    /** 录制状态定义 */
    public static enum RecordStatus {
        rs_created,							/**< 创建录制  */
        rs_recording,						/**< 正在录制（如果相应视频和音频流上传服务器，就会保持到录制中；如没数据也无录制） */
        rs_availble,						/**< 录制完成可查看  */
        rs_removed,							/**< 录制被删除  */
        rs_exception,						/**< 录制异常（如不完整等） */
    }

    /**
     * 录制数据结构.
     *
     * 录制数据定义了一个录制的基本信息。
     */
    public static class RecordInfo {
        String id;  					/**< 录制ID */
        String name;    				/**< 录制的名称 */
        String description;     		/**< 录制描述 */
        String tags;    				/**< 录制标记 */
        String userId;  				/**< 用户号，可不存在，存在时与audioType，videoType一起使用；录制此用户的相关音频和视频数据 */
        MediaFileType   fileType;	    /**< 媒体文件类型 */
        RecordAudioType audioType;      /**< 音频类型 */
        RecordVideoType videoType ;	    /**< 视频类型 */
        long size;  				    /**< 录制文件大小 */
        String createTime;  			/**< 录制创建起始时间 */
        long duration;  				/**< 录制从创建到现在的时长 */
        RecordStatus status;			/**< 录制状态 */
        String roomId;				    /**< 频道关联房间号 */
        String url;						/**< 播放录制链接,单个文件时 */
        List urls;		                /**< 播放录制链接列表,当录制是多个文件时,如录制mp4视频分辨率变化会产生多个文件 */

        public RecordInfo() {
            id = "";
            name = "";
            description = "";
            tags = "";
            userId = "";
            fileType = MediaFileType.mt_mp4;
            audioType = RecordAudioType.ra_none;
            videoType = RecordVideoType.rv_none;
            url = "";
            size = 0;
            createTime = "";
            duration = 0;
            status = RecordStatus.rs_created;
            roomId = "";
            urls = new LinkedList<String>();
        }
        protected RecordInfo(MediaFileType ft, RecordAudioType at, RecordVideoType vt, RecordStatus status, int size, int duration,
                             String id,String name, String description, String tags, String userId, String createTime, String roomId, String url, List urls) {
            this.fileType = ft;
            this.audioType = at;
            this.videoType = vt;
            this.size = size;
            this.duration = duration;
            this.id = id;
            this.status = status;
            this.name = name;
            this.description = description;
            this.tags = tags;
            this.userId = userId;
            this.url = url;
            this.createTime = createTime;
            this.roomId = roomId;
            this.urls = urls;
        }

        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 MediaFileType getFileType() { return this.fileType; }
        public int getFileTypeValue() { return this.fileType.ordinal(); }
        public void setFileType(MediaFileType value) { this.fileType = value; }
        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 getUrl() { return this.url; }
        public List getUrls() { return this.urls; }
        public long getSize() { return this.size; }
        public String getCreateTime() { return this.createTime; }
        public long getDuration() { return this.duration; }
        public RecordStatus getStatus() { return this.status; }
        public String getRoomId() { return this.roomId; }
        public void setRoomId(String value) { this.roomId = value; }

        @Override
        public boolean equals(Object obj) {
            RecordInfo objd = (RecordInfo) obj;
            if (null == objd) {
                return false;
            }
            return objd.getId().equals(this.getId());
        }
        @Override
        public String toString() {
            return "RecordInfo: 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 createUserRecord
         */
        public void onCreateUserRecord(int result, RecordInfo info);
        /** 停止特定录制的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] recordId 录制号。
         *
         * @sa stopRecord
         */
        public void onStopRecord(int result, String recordId);

        ///
        /** 获取特定录制详细信息的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] info 录制信息。
         *
         * @sa getRecordInfo
         */
        public void onRecordInfo(int result, RecordInfo info);
        /** 获取服务器上录制列表的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] total  总共直播数。
         * @param[in] begin  当前起始序号。
         * @param[in] items 录制信息集合。
         *
         * @sa getWorkingRecords
         */
        public void onRecordInfos(int result, int total, int begin, List<RecordInfo> items);
        /** 删除特定录制的异步返回
         *
         * @param[in] result 错误代码。
         * @param[in] recordId 录制号。
         *
         * @sa deleteRecord
         */
        public void onDeleteRecord(int result, String recordId);
    }

    ///
    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 AVDRecord INSTANCE = new AVDRecord();
    }
    private AVDRecord() {
        nativeobj = nativegetAVDRecord();
        if (0 == nativeobj) {
            throw new RuntimeException("Failed to Create AVDRecord!");
        }
    }

    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
     *		为异步操作，操作结果在 onCreateUserRecord 中返回。
     * @sa onCreateUserRecord
     */
    public int createUserRecord(RecordInfo info) {
        Tlog.d(TAG, "createUserRecord, info:" + info.toString());
        return nativecreateUserRecord(info);
    }
    /** 停止特定录制
     * @param[in] recordId 录制号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onStopRecord 中返回。
     * @sa onStopRecord
     */
    public int stopRecord(String recordId) {
        Tlog.d(TAG, "stopRecord, recordId:" + recordId);
        if (null == recordId || recordId.isEmpty()) {
            Tlog.e(TAG, "stopRecord, invalid recordId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativestopRecord(recordId);
    }
    /** 获取特定录制详细信息
     * @param[in] recordId 录制号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onRecordInfo 中返回。
     * @sa onRecordInfo
     */
    public int getRecordInfo(String recordId) {
        Tlog.d(TAG, "getRecordInfo, recordId:" + recordId);
        if (null == recordId || recordId.isEmpty()) {
            Tlog.e(TAG, "getRecordInfo, invalid recordId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativegetRecordInfo(recordId);
    }
    /** 获取服务器上的录制列表
     *
     * @param[in] begindex 分页的起始索引。
     * @param[in] ncount 分页的请求数量。
     * @param[in] filter 查询条件，以json表示，如：{ "roomId":"hafds2324" }。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onRecordInfos 中返回。
     * @sa onRecordInfos
     */
    public int findRecordInfos(int begindex, int ncount, String filter) {
        Tlog.d(TAG, "findRecordInfos, begindex:" + begindex+",ncount:"+ncount+",filter:"+filter);
        return nativefindRecordInfos(begindex, ncount, filter);
    }
    /** 删除特定录制
     *
     * @param[in] recordId 录制号。
     * @return 返回错误代码。
     * @note 为异步操作，操作结果在 onDeleteRecord 中返回。
     * @sa onDeleteRecord
     */
    public int deleteRecord(String recordId) {
        Tlog.d(TAG, "deleteRecord, recordId:" + recordId);
        if (null == recordId || recordId.isEmpty()) {
            Tlog.e(TAG, "deleteRecord, invalid recordId.");
            return ErrorCode.Err_Invalid_Arg;
        }
        return nativedeleteRecord(recordId);
    }

    ///
    private static native long nativegetAVDRecord();
    private native long nativeCreateListener(Listener listener);
    private native void nativeFreeListener(long nativeListener);
    private native int nativecreateUserRecord(RecordInfo info);
    private native int nativestopRecord(String recordId);
    private native int nativegetRecordInfo(String recordId);
    private native int nativefindRecordInfos(int begindex, int ncount, String filter);
    private native int nativedeleteRecord(String recordId);
    ///
    private static final int msg_onCreateUserRecord = 1;
    private static final int msg_onStopRecord = 2;
    private static final int msg_onRecordInfo = 3;
    private static final int msg_onRecordInfos = 4;
    private static final int msg_onDeleteRecord = 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(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_onCreateUserRecord:
                    listener4cb.onCreateUserRecord(msg.arg1, (RecordInfo) msg.obj);
                    break;
                case msg_onStopRecord:
                    listener4cb.onStopRecord(msg.arg1, (String) msg.obj);
                    break;
                case msg_onRecordInfo:
                    listener4cb.onRecordInfo(msg.arg1, (RecordInfo) msg.obj);
                    break;
                case msg_onRecordInfos:
                    listener4cb.onRecordInfos(msg.arg1, 0, 0, (List<RecordInfo>) msg.obj);
                    break;
                case msg_onDeleteRecord:
                    listener4cb.onDeleteRecord(msg.arg1, (String) msg.obj);
                    break;
            }
            super.handleMessage(msg);
            }
        };
        return true;
    }
    private class SDKListener implements Listener {
        public SDKListener() {
        }
        @Override
        public void onCreateUserRecord(int result, RecordInfo info) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onCreateUserRecord, result,0,info);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onStopRecord(int result, String recordId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onStopRecord, result,0,recordId);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onRecordInfo(int result, RecordInfo info) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onRecordInfo,  result,0,info);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onRecordInfos(int result, int total, int begin, List<RecordInfo> items) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onRecordInfos,  result,0,items);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onDeleteRecord(int result, String recordId) {
            if (null == listenerHandler) {
                return ;
            }
            android.os.Message msg = android.os.Message.obtain(listenerHandler,msg_onDeleteRecord,  result,0,recordId);
            listenerHandler.sendMessage(msg);
        }
    }
}
