package com.tencent.gme.audio.apiexample;


import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;

import androidx.appcompat.app.ActionBar;

import com.gme.TMG.ITMGContext;
import com.gme.TMG.ITMGRoom;
import com.gme.TMG.ITMGType;
import com.gme.av.sdk.AVError;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

public class RealTimeVoiceActivity extends BaseActivity implements TMGDispatcherBase,
        View.OnClickListener,
        CompoundButton.OnCheckedChangeListener,
        RadioGroup.OnCheckedChangeListener {
    private static final String sRoomId = "2018060";
    private EditText mRoomIdView;
    private TextView mLogMonitorView;
    private RadioGroup mRoomTypeView;
    private CheckBox mEnableMicView;
    private CheckBox mEnableSpeakerView;
    private ScrollView mLogHostView;

    private Map<String, TagUserInfo> mMapUserInfo = new HashMap<>();

    private static class TagUserInfo {
        public String name;
        public int volume;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_real_time_voice);

        initActionBar("Real Time Voice");

        initViews();
        mRoomIdView.setText(sRoomId);
        mRoomTypeView.check(R.id.rbRoomType1);
        TMGCallbackDispatcher.getInstance().registerSubDispatcher(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ITMGContext.GetInstance(this).ExitRoom();
        TMGCallbackDispatcher.getInstance().unregisterSubDispatcher(this);
    }

    private void initViews() {
        findViewById(R.id.ll_root).setOnClickListener(this);
        findViewById(R.id.btnEnterRoom).setOnClickListener(this);
        findViewById(R.id.btnExitRoom).setOnClickListener(this);
        findViewById(R.id.btnClear).setOnClickListener(this);
        findViewById(R.id.rbRoomType1).setOnClickListener(this);
        findViewById(R.id.rbRoomType2).setOnClickListener(this);
        findViewById(R.id.rbRoomType3).setOnClickListener(this);
        mEnableMicView = findViewById(R.id.checkEnableMic);
        mEnableSpeakerView = findViewById(R.id.checkEnableSpeaker);
        mEnableMicView.setOnCheckedChangeListener(this);
        mEnableSpeakerView.setOnCheckedChangeListener(this);
        mRoomIdView = findViewById(R.id.etRoomId);
        mRoomTypeView = findViewById(R.id.rgRoomType);
        mRoomTypeView.setOnCheckedChangeListener(this);
        mLogMonitorView = findViewById(R.id.tv_Monitor);
        mLogHostView = findViewById(R.id.sv_host);
    }

    @Override
    public void onClick(View v) {
        final int id = v.getId();
        if (id == R.id.btnEnterRoom) {
            onEnterRoomClick();
        } else if (id == R.id.btnExitRoom) {
            onExitRoomClick();
        } else if (id == R.id.btnClear) {
            mLogMonitorView.setText("");
        } else if (id == R.id.rbRoomType1) {
            int ret = ITMGContext.GetInstance(this).GetRoom().
                    ChangeRoomType(ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_FLUENCY);
            appendLog2MonitorView("ChangeRoomType to 1 ret :" + ret);
        } else if (id == R.id.rbRoomType2) {
            int ret =  ITMGContext.GetInstance(this).GetRoom().
                    ChangeRoomType(ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_STANDARD);
            appendLog2MonitorView("ChangeRoomType to 2 ret :" + ret);
        } else if (id == R.id.rbRoomType3) {
            int ret = ITMGContext.GetInstance(this).GetRoom().
                    ChangeRoomType(ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_HIGHQUALITY);
            appendLog2MonitorView("ChangeRoomType to 3 ret :" + ret);
        }
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {

    }

    private void onEnterRoomClick() {
        String roomId = mRoomIdView.getText().toString().trim();
        if (TextUtils.isEmpty(roomId)) {
            showToast("please input roomId");
            return;
        }

        int roomTypeCheckId = mRoomTypeView.getCheckedRadioButtonId();
        ITMGType.ITMG_ROOM_TYPE roomType = ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_FLUENCY;
        if (roomTypeCheckId == R.id.rbRoomType1) {
            roomType = ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_FLUENCY;
        } else if (roomTypeCheckId == R.id.rbRoomType2) {
            roomType = ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_STANDARD;
        } else if (roomTypeCheckId == R.id.rbRoomType3) {
            roomType = ITMGType.ITMG_ROOM_TYPE.ITMG_ROOM_TYPE_HIGHQUALITY;
        }

        byte[] authBuffer = GMEAuthBufferHelper.getInstance().createAuthBuffer(roomId);

        // Step 5/11 enter room, then you need handle ITMG_MAIN_EVENT_TYPE_ENTER_ROOM,ITMG_MAIN_EVENT_TYPE_USER_UPDATE
        // and ITMG_MAIN_EVENT_TYPE_ROOM_DISCONNECT event
        // https://cloud.tencent.com/document/product/607/15210#.3Ca-id.3D.22enterroom.22.3E.E5.8A.A0.E5.85.A5.E6.88.BF.E9.97.B4.3C.2Fa.3E
        int ret = ITMGContext.GetInstance(this).EnterRoom(roomId, roomType, authBuffer);
        appendLog2MonitorView(String.format("EnterRoom %s with type %d ret %d", roomId, roomType.getNativeValue(), ret));
    }

    private void onExitRoomClick() {
        // Step 10/11 exit room
        // 这里需要处理 ITMG_MAIN_EVENT_TYPE_EXIT_ROOM 事件
        // https://cloud.tencent.com/document/product/607/15210#.3Ca-id.3D.22exitroom.22.3E.E9.80.80.E5.87.BA.E6.88.BF.E9.97.B4.3C.2Fa.3E
        ITMGContext.GetInstance(this).ExitRoom();
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        ITMGContext gmeContext = ITMGContext.GetInstance(this);
        final int id = buttonView.getId();
        if (id == R.id.checkEnableMic) {
            // Step 8/11 enable to capture audio and send to server
            // https://cloud.tencent.com/document/product/607/15210#.3Ca-id.3D.22enablemic.22.3E.E5.BC.80.E5.90.AF.E6.88.96.E5.85.B3.E9.97.AD.E9.BA.A6.E5.85.8B.E9.A3.8E.3C.2Fa.3E
            int ret = gmeContext.GetAudioCtrl().EnableMic(isChecked);
        } else if (id == R.id.checkEnableSpeaker) {
            // Step 9/11 enable to capture audio and send to server
            // https://cloud.tencent.com/document/product/607/15210#.3Ca-id.3D.22enablespeaker.22.3E.E5.BC.80.E5.90.AF.E6.88.96.E5.85.B3.E9.97.AD.E6.89.AC.E5.A3.B0.E5.99.A8.3C.2Fa.3E
            gmeContext.GetAudioCtrl().EnableSpeaker(isChecked);
        }
    }

    @Override
    public void OnEvent(ITMGType.ITMG_MAIN_EVENT_TYPE type, Intent data) {
        if (type == ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_ENTER_ROOM) {
            // Step 6/11 : Perform the enter room event
            int nErrCode = TMGCallbackHelper.ParseIntentParams2(data).nErrCode;
            String strMsg = TMGCallbackHelper.ParseIntentParams2(data).strErrMsg;
            if (nErrCode == AVError.AV_OK) {
                appendLog2MonitorView("EnterRoom success");
            } else {
                appendLog2MonitorView(String.format(Locale.getDefault(), "EnterRoom errCode:%d errMsg:%s",
                        nErrCode, strMsg));
            }
        } else if (type == ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_USER_UPDATE) {
            // Step 7/11 : User in the room has new state, such as turn on/off microphone
            //			or new one enter/quit the room.
            //			more info please read the document.
            int nSubEvent = data.getIntExtra("event_id", 0);
            if (ITMGType.ITMG_EVENT_ID_USER_UPDATE.ITMG_EVENT_ID_USER_ENTER.getNativeValue() == nSubEvent) {
                String[] strUsers = data.getStringArrayExtra("user_list");
                if (strUsers != null && strUsers.length > 0) {
                    for (int i = 0; i < strUsers.length; i++) {
                        String userID = strUsers[i];
                        if (!mMapUserInfo.containsKey(userID)) {
                            //如果不在房间里
                            TagUserInfo userInfo = new TagUserInfo();
                            userInfo.name = userID;
                            userInfo.volume = 0;
                            mMapUserInfo.put(userID, userInfo);
                        }
                    }
                    appendLog2MonitorView("UserUpdate complete:" + convertMapToString(mMapUserInfo));
                }
            } else if (ITMGType.ITMG_EVENT_ID_USER_UPDATE.ITMG_EVENT_ID_USER_EXIT.getNativeValue() == nSubEvent) {
                String[] strUsers = data.getStringArrayExtra("user_list");
                if (strUsers != null && strUsers.length > 0) {
                    for (int i = 0; i < strUsers.length; i++) {
                        String userID = strUsers[i];
                        if (mMapUserInfo.containsKey(userID)) {
                            //如果不在房间里
                            mMapUserInfo.remove(userID);
                        }
                    }
                }
                appendLog2MonitorView("UserUpdate complete:" + convertMapToString(mMapUserInfo));
            } else if (ITMGType.ITMG_EVENT_ID_USER_UPDATE.ITMG_EVENT_ID_USER_HAS_AUDIO.getNativeValue() == nSubEvent) {
                String[] strUsers = data.getStringArrayExtra("user_list");
                appendLog2MonitorView("UserUpdate has audio:" + Arrays.toString(strUsers));
            } else if (ITMGType.ITMG_EVENT_ID_USER_UPDATE.ITMG_EVENT_ID_USER_NO_AUDIO.getNativeValue() == nSubEvent) {
                String[] strUsers = data.getStringArrayExtra("user_list");
                appendLog2MonitorView("UserUpdate no audio:" + Arrays.toString(strUsers));
            }
        } else if (type == ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_EXIT_ROOM) {
            // Step 11/11 : Perform the exit room event
            appendLog2MonitorView("ExitRoom success");
            mEnableMicView.setChecked(false);
            mEnableSpeakerView.setChecked(false);
            mRoomTypeView.check(R.id.rbRoomType1);
        } else if (type == ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_ROOM_DISCONNECT) {
            appendLog2MonitorView("Disconnect with server");
        } else if (type == ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_CHANGE_ROOM_TYPE) {
            //切换房间类型回调
//            int code = data.getIntExtra("result", 0);
//            String strErrInfo = data.getStringExtra("error_info");
//            int nNewRoomType = data.getIntExtra("new_room_type", 0);
//            int nSubEventType = data.getIntExtra("sub_event_type", 0);
//            switch (nSubEventType) {
//                case ITMGType.ITMG_ROOM_CHANGE_EVENT_ENTERROOM:
//                case ITMGType.ITMG_ROOM_CHANGE_EVENT_COMPLETE:
//                    switch (nNewRoomType) {
//                        case 1:
//                            mRoomTypeView.check(R.id.rbRoomType1);
//                            break;
//                        case 2:
//                            mRoomTypeView.check(R.id.rbRoomType2);
//                            break;
//                        case 3:
//                            mRoomTypeView.check(R.id.rbRoomType3);
//                            break;
//                    }
//                    showToast("Roomtype changed");
//                    appendLog2MonitorView("ChangeRoomtype roomtype change to " + nNewRoomType);
//                    break;
//                default:
//            }
        } else if (ITMGType.ITMG_MAIN_EVENT_TYPE.ITMG_MAIN_EVENT_TYPE_USER_VOLUMES == type) {
            Bundle bundle = data.getExtras();
            for (String userId : bundle.keySet()) {
                if (mMapUserInfo.containsKey(userId) && mMapUserInfo.get(userId) != null) {
                    mMapUserInfo.get(userId).volume = data.getIntExtra(userId, 0);
                }
            }
        }
    }

    private void appendLog2MonitorView(String text) {
        String logText = mLogMonitorView.getText().toString();
        if (!logText.isEmpty()) {
            logText = logText + "\n" + text;
        } else {
            logText = text;
        }
        mLogMonitorView.setText(logText);
        mLogHostView.fullScroll(View.FOCUS_DOWN);
    }

    public static String convertMapToString(Map<String, TagUserInfo> map) {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        Iterator<Map.Entry<String, TagUserInfo>> it = map.entrySet().iterator();
        String split = "";
        while (it.hasNext()) {
            sb.append(split);
            Map.Entry<String, TagUserInfo> entry = it.next();
            sb.append(entry.getKey());
            split = ",";
        }
        sb.append("}");
        return sb.toString();
    }
}