package cn.tee3.avd;

import android.os.Handler;
import android.os.Message;

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

/**
 * 直播接口类
 *
 * 直播接口定义了直播对象创建和释放、直播功能操作。
 */
public class Livecast {
    private static final String TAG = "Livecast";
    /** 客户端直播状态定义 */
    public static enum LivecastStatus
    {
        lc_init,							/**< 初始状态 */
        lc_connecting,						/**< 正在连接服务器 */
        lc_livecast,						/**< 正在直播  */
        lc_dialogue,						/**< 正在互动连麦  */
        lc_reconnecting,					/**< 正在与服务器重连接  */
    }
    /**
     * 直播回调接口类
     *
     * 直播回调接口定义了直播对象操作的异步返回，直播状态通知等。
     */
    public static interface Listener {
        /// 通知
        /** 直播状态更改通知
         *
         * @param[in] status 当前直播状态。
         */
        public void onLivecastStatus(LivecastStatus status);
    }

    protected long nativeobj;
    protected long nativeListener;
    protected Listener listener4cb = null;
    protected Handler listenerHandler = null;
    protected SDKListener listener4native = null;
    protected Livecast(String roomId, boolean isMainBroadcaster) {
        initHandler();
        this.nativeobj = nativeobtain(roomId, isMainBroadcaster);
        if (0 == nativeobj) {
            throw new RuntimeException("Failed to Create Livecast!");
        }
        AudioRoute.instance();
        Tlog.i(TAG, "Livecast, roomId:" + roomId + "this=" + this + ",nativeobj=" + this.nativeobj);
    }

    ///
    protected static List<Livecast> rooms = null;
    /** 获取或创建房间接口
     *
     * @param[in] roomId 房间Id。
     * @note 只支持单用户应用，不支持多用户应用。
     * @return 返回房间接口指针。
     */
    protected static Livecast obtain(String roomId) {
        if (null == rooms) {
            rooms = new LinkedList<Livecast>();
        }
        synchronized (rooms) {
            Iterator<Livecast> it = rooms.iterator();
            while (it.hasNext()) {
                Livecast room = it.next();
                if (room.getRoomId().equals(roomId)) {
                    return room;
                }
            }
        }
        return null;
    }
    protected static void clearRooms() {
        if (null == rooms) {
            return ;
        }
        Tlog.i(TAG, "clearRooms, rooms:" + rooms.size());
        synchronized (rooms) {
            Iterator<Livecast> it = rooms.iterator();
            while (it.hasNext()) {
                Livecast room = it.next();
                room.dispose();
            }
            rooms.clear();
        }
    }

    /** 释放房间接口
     *@note 释放房间后，App层不能再使用当前房间指针，所有引用房间指针处均需设置为NULL。
     */
    public static void destoryRoom(Livecast room) {
        Tlog.i(TAG, "destoryRoom, room:" + room);
        if (null == room) {
            return ;
        }
        //
        synchronized (rooms) {
            rooms.remove(room);
        }
        room.dispose();
        Tlog.v(TAG, "destoryRoom, out:");
    }
    /** 设置房间回调接口
     *
     * @param[in] listener 回调接口指针。
     *
     * @return 返回错误代码。
     * @see Listener
     */
    public int setListener(Listener listener) {
        Tlog.i(TAG, "setListener, nativeRoom:" + nativeobj + ",listener:" + listener);
        this.listener4cb = listener;
        if (0 == this.nativeListener) {
            this.nativeListener = nativeCreateListener(this.listener4native);
            nativesetListener(this.nativeListener);
        }
        Tlog.v(TAG, "setListener, out:");
        return 0;
    }

    // 主播和连麦观众接口
    /** 判断是否连麦状态
     */
    public boolean isDialogue() {
        return nativeisDialogue();
    }
    /** 挂断连麦对话
     * @note 主播和连麦观众都可以挂断对话
     */
    public int hangup() {
        Tlog.i(TAG, "hangup, ");
        return nativehangup();
    }
    /** 抓取直播图像
     *
     * @param[in] fileName 图像保存地址，绝对地址。
     * @param[in] quality  图像质量：0-100, 0最差，100最好。
     * @return 返回错误代码。
     * @note 目前在直播状态下，播放端无法抓取视频（rtmp播放器播放的时候）
     */
    public int captureImage(String fileName, int quality) {
        Tlog.i(TAG, "captureImage, fileName:"+fileName+",quality:"+quality);
        return nativecaptureImage(fileName,quality);
    }

    /** 获取用户管理接口
     * @sa IMUserManager
     */
    public MUserManager getUserManager() {
        return null;
    }
    /** 获取直播房间状态
     *
     * @return 返回直播房间状态。
     * @sa LivecastStatus
     */
    public LivecastStatus getLiveStatus() {
        return nativegetLiveStatus();
    }

    /** 获取直播房间Id
     *
     * @return 返回直播房间Id。
     */
    public String getRoomId() {
        return nativegetRoomId();
    }
    /// 控制接口, switch, mute...
    /** 本地麦克风静默及取消
     * @param[in] isMute 静默标示。
     * @return 返回错误代码。
     */
    public int muteMicrophone(boolean isMute) {
        Tlog.i(TAG, "muteMicrophone,isMute="+isMute);
        return nativemuteMicrophone(isMute);
    }
    /** 直播切换摄像头
     *
     * @return 返回错误代码。
     */
    public int switchCamera() {
        Tlog.i(TAG, "switchCamera,");
        return nativerswitchCamera();
    }
    /** 开启直播（主播）或对讲（观众）前: 设置视频的输入数据源
     *
     * @param[in] *vcapturer 视频的输入数据源。
     * @return 返回错误代码。
     * @sa FakeVideoCapturer
     */
    public int setVideoSource(FakeVideoCapturer vcapturer) {
        Tlog.i(TAG, "setVideoSource,vcapturer="+vcapturer);
        return nativesetVideoSource((null == vcapturer) ? 0 : vcapturer.getNativeobj());
    }
    //
    /** 设置房间选项
     *
     * @param[in] type 房间选项类型。
     * @param[in] svalue 房间选项值。
     *
     * @return 返回错误代码。
     */
    public int setOption(Room.Option type, String svalue) {
        Tlog.i(TAG, "setOption, type:" + type + ",svalue:" + svalue);
        return nativersetOption(type.ordinal(), svalue);
    }
    /** 获取房间选项
     *
     * @param[in] type 房间选项类型。
     *
     * @return 返回房间选项值。
     */
    public String getOption(Room.Option type) {
        return nativergetOption(type.ordinal());
    }
    ///
    protected static native long nativeobtain(String roomId, boolean isMainBroadcaster);
    protected static native void nativerelease(long nativeRoom);
    protected static native long nativeCreateListener(Listener listener);
    protected static native void nativeFreeListener(long nativeListener);
    //
    protected native int nativesetListener(long nativelistener);
    protected native int nativereConnect();
    // main broadcaster
    protected native int nativemainbdsetListener2(long nativerender);
    protected native int nativepublish(String playUrl, long nativerender);
    protected native int nativeunpublish();
    protected native int nativekickoutUser(int reason, String userId);
    // live video layout
    protected native List<VideoDevice> nativegetPublishedVideos();
    protected native int nativesetLiveVideoTypeaSize(int layout, int width, int height);
    protected native int nativesetLiveVideoScaleType(int scale);
    protected native int nativesetLiveVideoBackgroud(String background);
    protected native void nativeclearLiveSubVideos();
    protected native int nativesetLiveMainVideo(String deviceId);
    protected native int nativeautoLayoutParams(boolean isTopdown, float w, float h, float x_begin, float y_begin);
    protected native int nativeaddLiveSubVideo(String deviceId, int zorder, float x, float y, float w, float h);
    protected native int nativeupdateLiveSubVideo(String deviceId, int zorder, float x, float y, float w, float h);
    protected native void nativeremoveLiveSubVideo(String deviceId);
    // livecast viewer
    protected native int nativeviewersetListener2(long nativerender);
    protected native int nativesetBroadcasterId(String svalue);
    protected native int nativewatchRoom(String playUrl, long nativerender);
    protected native int nativedialogue();
    // common
    protected native boolean nativeisDialogue();
    protected native int nativehangup();
    protected native LivecastStatus nativegetLiveStatus();
    protected native String nativegetRoomId();
    protected native int nativerswitchCamera();
    protected native int nativemuteMicrophone(boolean isMute);
    protected native int nativesetVideoSource(long nativeobj);
    protected native int nativecaptureImage(String fileDir, int quality);
    //
    protected native int nativersetOption(int type, String svalue);
    protected native String nativergetOption(int type);
    //
    protected native long nativegetMUserManager();
    ///
    protected void dispose() {
        Tlog.d(TAG, "Room dispose ");
        listener4cb = null;
        if (null != this._netProber) {
            NetworkProber.instance().unregisterReceiver(this._netProber);
            _netProber = null;
        }
        nativesetListener(0);
        if (0 != this.nativeListener) {
            nativeFreeListener(this.nativeListener);
            this.nativeListener = 0;
        }
        if (0 != this.nativeobj) {
            nativerelease(this.nativeobj);
            this.nativeobj = 0;
        }
        listenerHandler = null;
        listener4native = null;
        Tlog.d(TAG, "dispose, out:");
    }

    ///
    protected NetworkProberLister _netProber = null;
    class NetworkProberLister implements NetworkProber.Listener {
        public void onNetworkChanged(NetworkProber.Status status) {
            Tlog.v(TAG, "onNetworkChanged status="+status);
            if (status != NetworkProber.Status.Network_Diconnected) {
                nativereConnect();
            }
        }
    }
    protected void beginNetProber() {
        if (null == this._netProber) {
            this._netProber = new NetworkProberLister();
            NetworkProber.instance().registerReceiver(this._netProber);
        }
    }
    ///
    protected final int msg_onLivecastStatus = 1;
    protected final int msg_onPublishResult = 100;
    protected final int msg_onDialogueResult = 200;
    protected final int msg_onRtmpPlay = 201;
    protected final int msg_onRtmpStop = 202;
    protected boolean initHandler() {
        if (null == listener4native) {
            listener4native = new SDKListener();
        }
        return true;
    }
    protected class ListenerHandler extends Handler {
        public ListenerHandler() {
        }
        public void handleMessage(Message msg) {
            Tlog.v(TAG, "handleMessage, msg:"+msg.toString());
            if (null == listener4cb) {
                super.handleMessage(msg);
                return;
            }
            switch (msg.what) {
                case msg_onLivecastStatus:
                    listener4cb.onLivecastStatus(LivecastStatus.values()[msg.arg1]);
                    break;
            }
            super.handleMessage(msg);
        }
    }
    protected class SDKListener implements Listener, MainBroadcaster.Listener, LivecastViewer.Listener {
        public SDKListener() {
        }
        @Override
        public void onLivecastStatus(LivecastStatus status) {
            if (null == listenerHandler) {
                return ;
            }
            Message msg = Message.obtain(listenerHandler, msg_onLivecastStatus, status.ordinal(),0);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onPublishResult(int result) {
            if (null == listenerHandler) {
                return ;
            }
            Message msg = Message.obtain(listenerHandler, msg_onPublishResult, result, 0);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onDialogueResult(int result) {
            if (null == listenerHandler) {
                return ;
            }
            Message msg = Message.obtain(listenerHandler, msg_onDialogueResult, result, 0);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onRtmpPlay(String url) {
            if (null == listenerHandler) {
                return ;
            }
            Message msg = Message.obtain(listenerHandler, msg_onRtmpPlay, url);
            listenerHandler.sendMessage(msg);
        }
        @Override
        public void onRtmpStop() {
            if (null == listenerHandler) {
                return ;
            }
            Message msg = Message.obtain(listenerHandler, msg_onRtmpStop);
            listenerHandler.sendMessage(msg);
        }

    }
}
