package com.tencent.trtc.videocall;

import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.tencent.trtc.CordovaEventKit;
import com.tencent.trtc.CustomVideoView;
import com.tencent.trtc.TRTCBaseActivity;

import com.tencent.liteav.device.TXDeviceManager;
import com.tencent.trtc.TRTCCloud;
import com.tencent.trtc.TRTCCloudDef;
import com.tencent.trtc.TRTCCloudListener;
import com.tencent.trtc.debug.Constant;
import com.tencent.trtc.event.Events;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * TRTC视频通话的主页面
 * <p>
 * 包含如下简单功能：
 * - 进入视频通话房间{@link VideoCallingActivity#enterRoom()}
 * - 退出视频通话房间{@link VideoCallingActivity#exitRoom()}
 * - 切换前置/后置摄像头{@link VideoCallingActivity#switchCamera()}
 * - 打开/关闭摄像头{@link VideoCallingActivity#muteVideo()}
 * - 打开/关闭麦克风{@link VideoCallingActivity#muteAudio()}
 * - 显示房间内其他用户的视频画面（当前示例最多可显示6个其他用户的视频画面）{@link TRTCCloudImplListener#refreshRemoteVideoViews()}
 * <p>
 * - 详见接入文档{https://cloud.tencent.com/document/product/647/42045}
 */

/**
 * Video Call
 *
 * Features:
 * - Enter a video call room: {@link VideoCallingActivity#enterRoom()}
 * - Exit a video call room: {@link VideoCallingActivity#exitRoom()}
 * - Switch between the front and rear cameras: {@link VideoCallingActivity#switchCamera()}
 * - Turn on/off the camera: {@link VideoCallingActivity#muteVideo()}
 * - Turn on/off the mic: {@link VideoCallingActivity#muteAudio()}
 * - Display the video of other users (max. 6) in the room: {@link TRTCCloudImplListener#refreshRemoteVideoViews()}
 *
 * - For more information, please see the integration document {https://cloud.tencent.com/document/product/647/42045}.
 */
public class VideoCallingActivity extends TRTCBaseActivity implements View.OnClickListener {

    private static final String TAG = "VideoCallingActivity";
    private static final int OVERLAY_PERMISSION_REQ_CODE = 1234;

    private TextView mTextTitle;
//    private CustomVideoView mTXCVVLocalPreviewView;
    private ImageView mImageBack;
    private ImageView mButtonMuteVideo;
    private ImageView mButtonMuteAudio;
    private ImageView mButtonSwitchCamera;
    private ImageView mButtonAudioRoute;

    private TRTCCloud mTRTCCloud;
    private TXDeviceManager mTXDeviceManager;
    private boolean mIsFrontCamera = true;
    private List<UserInfo> mUserList;
    private List<CustomVideoView> mRemoteViewList;
    private int mUserCount = 0;
    private String mRoomId;
    private String mUserId;
    private int sdkAppId;
    private String userSig;
    private boolean hideSub;
    private boolean mAudioRouteFlag = true;

    private UserInfo localUserInfo;

    private int getId(String idName, String type) {
        return getResources().getIdentifier(idName, type, getPackageName());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        R.layout.videocall_activity_calling
        setContentView(getId("videocall_activity_calling", "layout"));
        getSupportActionBar().hide();
        handleIntent();

        if (checkPermission()) {
            initView();
            enterRoom();
        }
    }

    private void handleIntent() {
        Intent intent = getIntent();
        if (null != intent) {
            if (intent.getStringExtra(Constant.USER_ID) != null) {
                mUserId = intent.getStringExtra(Constant.USER_ID);
            }
            if (intent.getStringExtra(Constant.ROOM_ID) != null) {
                mRoomId = intent.getStringExtra(Constant.ROOM_ID);
            }

            if (intent.getIntExtra(Constant.SDK_APP_ID, 0) != 0) {
                sdkAppId = intent.getIntExtra(Constant.SDK_APP_ID, 0);
            }

            if (intent.getStringExtra(Constant.USER_SIG) != null) {
                userSig = intent.getStringExtra(Constant.USER_SIG);
            }
        }
        System.out.println("sdkAppId = " + sdkAppId);
        System.out.println("userSig = " + userSig);
    }

    private void initView() {
//      R.id.tv_room_number
        mTextTitle = findViewById(getId("tv_room_number", "id"));
//      R.id.iv_back
        mImageBack = findViewById(getId("iv_back", "id"));
//      R.id.txcvv_main
//      R.id.btn_mute_video
        mButtonMuteVideo = findViewById(getId("btn_mute_video", "id"));
//      R.id.btn_mute_audio
        mButtonMuteAudio = findViewById(getId("btn_mute_audio", "id"));
//      R.id.btn_switch_camera
        mButtonSwitchCamera = findViewById(getId("btn_switch_camera", "id"));
//      R.id.btn_audio_route
        mButtonAudioRoute = findViewById(getId("btn_audio_route", "id"));

        if (!TextUtils.isEmpty(mRoomId)) {
            mTextTitle.setText(getString(getId("videocall_roomid", "string")) + mRoomId);
        }
        mImageBack.setOnClickListener(this);
        mButtonMuteVideo.setOnClickListener(this);
        mButtonMuteAudio.setOnClickListener(this);
        mButtonSwitchCamera.setOnClickListener(this);
        mButtonAudioRoute.setOnClickListener(this);

        mUserList = new ArrayList<>();
        localUserInfo = new UserInfo().setPersonid(mUserId).setLocal(true)
                .setDisplayName("我").setFrontCamera(mIsFrontCamera);
        mUserList.add(localUserInfo);
        mRemoteViewList = new ArrayList<>();
        for(int i=0;i<7;i++){
            CustomVideoView videoView = ((CustomVideoView) findViewById(getId("trtc_view_"+i, "id"))).setMainView(i == 0);
            if(i > 0){
                videoView.setOnClickListener((view)->{
                    if(view instanceof  CustomVideoView && !((CustomVideoView) view).isMainView()){
                        UserInfo mainUser = this.mUserList.get(0);
                        UserInfo viewUser = ((CustomVideoView) view).getUserInfo();
                        Collections.swap(this.mUserList,0,this.mUserList.indexOf(viewUser));
                        mTRTCCloud.stopLocalPreview();
                        mTRTCCloud.stopLocalAudio();
                        mRemoteViewList.get(0).changeUser(mTRTCCloud,viewUser);
                        ((CustomVideoView) view).changeUser(mTRTCCloud,mainUser);
                        try {
                            JSONObject object = new JSONObject();
                            object.put("room",mRoomId);
                            object.put("userId",viewUser.getPersonid());
                            CordovaEventKit.kit.fireEvent("onLayoutChangeMessage",object);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            mRemoteViewList.add(videoView);
        }
        Events.fireEvent("subview.always.hide",(extra)->extra.putBoolean("alwaysHide",false));

        Events.addListener("userinfo.update",(extra -> {
            String user = extra.getString("userId");
            int index = this.mUserList.indexOf(user);
            if(index > -1){
                this.mUserList.get(index).setDisplayName(extra.getString("displayName"));
            }
        }));
    }

    private void enterRoom() {
        mTRTCCloud = TRTCCloud.sharedInstance(getApplicationContext());
        mTRTCCloud.setListener(new TRTCCloudImplListener(VideoCallingActivity.this));
        mTXDeviceManager = mTRTCCloud.getDeviceManager();

        TRTCCloudDef.TRTCParams trtcParams = new TRTCCloudDef.TRTCParams();
        trtcParams.sdkAppId = this.sdkAppId;
        trtcParams.userId = mUserId;
        trtcParams.roomId = Integer.parseInt(mRoomId);
        trtcParams.userSig = this.userSig;

        mRemoteViewList.get(0).changeUser(mTRTCCloud, mUserList.get(0));
        mTRTCCloud.enterRoom(trtcParams, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);
        JSONObject object = new JSONObject();
        try {
            object.put("room",mRoomId);
            object.put("userId",mUserId);
            CordovaEventKit.kit.fireEvent("onLayoutChangeMessage",object);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        exitRoom();
    }

    private void exitRoom() {
        if (mTRTCCloud != null) {
            mTRTCCloud.stopLocalAudio();
            mTRTCCloud.stopLocalPreview();
            mTRTCCloud.exitRoom();
            mTRTCCloud.setListener(null);
        }
        mTRTCCloud = null;
        TRTCCloud.destroySharedInstance();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onPermissionGranted() {
        initView();
        enterRoom();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == getId("iv_back", "id")) {
            finish();
        } else if (id == getId("btn_mute_video", "id")) {
            muteVideo();
        } else if (id == getId("btn_mute_audio", "id")) {
            muteAudio();
        } else if (id == getId("btn_switch_camera", "id")) {
            switchCamera();
        } else if (id == getId("btn_audio_route", "id")) {
            audioRoute();
        }
    }


    private void muteVideo() {
        boolean isSelected = mButtonMuteVideo.isSelected();
        if (!isSelected) {
            mButtonMuteVideo.setImageDrawable(getDrawable(getId("view_open", "mipmap")));
        } else {
            mButtonMuteVideo.setImageDrawable(getDrawable(getId("view_close", "mipmap")));
        }
        Events.fireEvent("subview.always.hide",(extra)->extra.putBoolean("alwaysHide",!isSelected));
        mButtonMuteVideo.setSelected(!isSelected);
    }

    private void muteAudio() {
        boolean isSelected = mButtonMuteAudio.isSelected();
        if (!isSelected) {
            mTRTCCloud.muteLocalAudio(true);
            mButtonMuteAudio.setImageDrawable(getDrawable(getId("mac_on", "mipmap")));
        } else {
            mTRTCCloud.muteLocalAudio(false);
            mButtonMuteAudio.setImageDrawable(getDrawable(getId("mac_off", "mipmap")));
        }
        mButtonMuteAudio.setSelected(!isSelected);
    }

    private void switchCamera() {
        mIsFrontCamera = !mIsFrontCamera;
        localUserInfo.setFrontCamera(mIsFrontCamera);
        mTXDeviceManager.switchCamera(mIsFrontCamera);
    }

    private void audioRoute() {
        if (mAudioRouteFlag) {
            mAudioRouteFlag = false;
            mTXDeviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteEarpiece);
            mButtonAudioRoute.setImageDrawable(getDrawable(getId("earpiece", "mipmap")));
        } else {
            mAudioRouteFlag = true;
            mTXDeviceManager.setAudioRoute(TXDeviceManager.TXAudioRoute.TXAudioRouteSpeakerphone);
            mButtonAudioRoute.setImageDrawable(getDrawable(getId("speaker", "mipmap")));
        }
    }


    private class TRTCCloudImplListener extends TRTCCloudListener {

        private WeakReference<VideoCallingActivity> mContext;

        public TRTCCloudImplListener(VideoCallingActivity activity) {
            super();
            mContext = new WeakReference<>(activity);
        }

        @Override
        public void onUserVideoAvailable(String userId, boolean available) {
            Log.d(TAG, "onUserVideoAvailable userId " + userId + ", mUserCount " + mUserCount + ",available " + available);
            UserInfo info = new UserInfo().setPersonid(userId);
            int index = mUserList.indexOf(info);
            if (available) {
                if (index != -1) {
                    return;
                }
                mUserList.add(info);
                refreshRemoteVideoViews();
            } else {
                if (index == -1) {
                    return;
                }
                mTRTCCloud.stopRemoteView(userId);
                mUserList.remove(index);
                refreshRemoteVideoViews();
            }

            JSONObject object = new JSONObject();
            try {
                object.put("room",mRoomId);
                object.put("userId",userId);
                object.put("available",available);
                CordovaEventKit.kit.fireEvent("onUserVideoAvailable",object);
            } catch (JSONException e) {
                e.printStackTrace();
            }

        }

        private void refreshRemoteVideoViews() {
            for (int i = 0; i < mRemoteViewList.size(); i++) {
                if (i < mUserList.size()) {
                    UserInfo user = mUserList.get(i);
                    mRemoteViewList.get(i).changeUser(mTRTCCloud,user);
                } else {
                    mRemoteViewList.get(i).changeUser(mTRTCCloud,null);
                }
            }
        }

        @Override
        public void onError(int errCode, String errMsg, Bundle extraInfo) {
            Log.d(TAG, "sdk callback onError");
            VideoCallingActivity activity = mContext.get();
            if (activity != null) {
                Toast.makeText(activity, "onError: " + errMsg + "[" + errCode + "]", Toast.LENGTH_SHORT).show();
                finish();
            }
        }

        @Override
        public void onExitRoom(int reason) {
            super.onExitRoom(reason);
            if (reason == 2) {
                VideoCallingActivity activity = mContext.get();
                Toast.makeText(activity, "远程协助已结束", Toast.LENGTH_LONG).show();
            }
            finish();
        }

    }

}
