package cn.tee3.dev.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Environment;
import android.os.Process;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import rtc.AVDEngine;
import rtc.ErrorCode;
import rtc.Room;
import rtc.RoomInfo;
import rtc.User;
import cn.tee3.dev.activity.utils.RequestPermissions;
import cn.tee3.dev.R;

/**
 * 大小图、画廊、
 */
public class JoinMeetActivity extends Activity {
    private EditText etRoomId;
    private EditText etUserName;
    private String roomId;
    private String userName;

    public static String serverURI = "http://v.nice2meet.cn";     // 默认的服务器地址
    public static String accessKey = "demo_access";            // 会议凭证
    public static String secretKey = "demo_secret";            // 会议密匙

    /**
     * 本地发布视频分辨率和最大帧率（宽、高、帧率）
     */
    public enum Resolution {
        MINI("{\"width\":480,\"height\":360,\"maxFPS\":20}"),
        LOW("{\"width\":640,\"height\":480,\"maxFPS\":20}"),
        MIDDLE("{\"width\":1280,\"height\":720,\"maxFPS\":30}"),
        HIGH("{\"width\":1920,\"height\":1080,\"maxFPS\":20}");
        private final String value;

        Resolution(String value) {
            this.value = value;
        }
    }

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

        initView();
        requestPermissions();
    }

    private void initView() {
        etRoomId = findViewById(R.id.etRoomId);
        etUserName = findViewById(R.id.etUserName);
        etUserName.setText(Build.BRAND + System.currentTimeMillis() % 1000);
        String roomId = "r" + System.currentTimeMillis() / 1000;    // 随机房间号，可根据自己的需求修改为固定的房间号。
        etRoomId.setText(roomId);
    }

    /**
     * 动态获取权限，对权限是否通过未做处理。
     */
    private void requestPermissions() {
        RequestPermissions.permissionHelper(this)
                .request(null,
                        Manifest.permission.CAMERA,
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.READ_PHONE_STATE);
    }

    /**
     * 加入房间
     */
    public void onClickJoinRoom(View view) {
        roomId = etRoomId.getText().toString();
        userName = etUserName.getText().toString();
        if (roomId.length() == 0) {
            Toast.makeText(this, "RoomId 为空！", Toast.LENGTH_SHORT).show();
            return;
        }
        engineInit(AVDEngineListener);  // 初始化引擎并加入房间
    }

    /**
     * 加入房间
     */
    private void joinRoom() {
        Room room = Room.obtain(roomId);    // 获取房间（SDK引擎已初始化）
        if (room == null) {
            return;
        }
        room.setOption(Room.Option.ro_media_use_dtls, "true");      // 使用DTLS音视频加密算法
        room.setOption(Room.Option.ro_room_rejoin_times, "-1");     // 设置网络波动断开房间连接后做一直重连操作
        room.setOption(Room.Option.ro_audio_option_codec, "opus");  // 音频编码格式opus
        room.setOption(Room.Option.ro_audio_auto_subscribe, "true");  // 音频自动订阅
        room.enableStats(true);     // 使能房间内媒体统计（监测每路视频分辨率、帧率、码流，音频码流等信息）

        // TODO: 2021/5/24 用户名（参数1）需要唯一，否则会被同名用户顶下线。
        User user = new User(userName, userName, 0, "", "");    // 创建用户（用户名：userName， 用户id：userName）。
        // 加入房间
        room.join(user, "", new Room.JoinResultListener() {
            @Override
            public void onJoinResult(int result) {
                if (result == ErrorCode.AVD_OK) {   // 加入房间成功
                    Intent intent = new Intent(JoinMeetActivity.this, MeetingActivity.class);
                    intent.putExtra("ROOM_ID", roomId);
                    startActivity(intent);
                } else {
                    Toast.makeText(JoinMeetActivity.this, "加入房间失败：" + result, Toast.LENGTH_LONG).show();
                }
            }
        });
    }

    /**
     * 初始化引擎
     */
    private void engineInit(AVDEngine.Listener listener) {
        logFileConfig();        // 设置日志
        setAVDEngineOptions();  // 设置引擎选项
        engineSetup(listener);  // 初始化引擎
    }

    /**
     * AVDSDK日志配置
     */
    public void logFileConfig() {
        @SuppressLint("SimpleDateFormat") DateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String logPath = "doubleRecord/" + "doubleRecord" + format.format(new Date()) + ".log";
        logPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + logPath;   // 日志路径
        String params = "debug " +  // 调试模式
                        "verbose " +        // 日志等级详细等级
                        "stats " +          // 日志开启媒体统计（会动态的将视频和音频信息打印到日志文件里）
                        "append " +         // 不释放引擎的情况下多次加会和离会操作按照先后顺序打印到一个日志文件里，即初始化~释放引擎一个周期对应一个日志输出。
                        "realtstamp";       // 日志日期使用真实时间，格式： 月份-日期 时:分:秒

        AVDEngine.instance().setLogParams(params, logPath); // 设置日志
    }

    /**
     * 启动引擎，会触发异步回调 AVDEngineListener.onInitResult
     */
    public void engineSetup(AVDEngine.Listener listener) {
        int result = AVDEngine.instance().init(this, listener, serverURI, accessKey, secretKey);
        if (result != ErrorCode.AVD_OK) {
            Toast.makeText(this, "初始化引擎失败：" + result, Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 设置AVDSDK引擎选项
     */
    private void setAVDEngineOptions() {
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_swapwh_by_rotation, "false");      // 不变换宽高严格按设置分辨率裁剪拉伸
        AVDEngine.instance().setOption(AVDEngine.Option.eo_camera_mode_frontback, "true");          // 使用前后置双摄像头模式
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_resolution_16balign, "true");      // 分辨率16位自动对齐
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_codec_hw_priority, "true");        // 优先使用硬件编解码
        AVDEngine.instance().setOption(AVDEngine.Option.eo_audio_aec_Enable, "true");               // 开启回音消除
        AVDEngine.instance().setOption(AVDEngine.Option.eo_audio_aec_DAEcho_Enable, "true");        // 启用延时消除算法
        AVDEngine.instance().setOption(AVDEngine.Option.eo_audio_autoGainControl_Enable, "true");   // 麦克风输入自动增益
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_renderusecapture, "true");         // 渲染视频时直接渲染方式不做拉伸变形
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_codec_priority, "h264");           // 优先使用H264编码
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_codec_hw_encode, "true");          // 优先使用硬编码
        AVDEngine.instance().setOption(AVDEngine.Option.eo_video_codec_hw_decode, "true");          // 优先使用硬解码
        AVDEngine.instance().setOption(AVDEngine.Option.eo_data_channel_tcp_priority, "false");     // 房间数据通道优先使用UDP（缺省值）
        AVDEngine.instance().setOption(AVDEngine.Option.eo_camera_capability_default, Resolution.MIDDLE.value); // 设置发布视频的分辨率和帧率 1280*720 30帧
    }

    AVDEngine.Listener AVDEngineListener = new AVDEngine.Listener() {
        @Override
        public void onInitResult(int result) {
            if (ErrorCode.AVD_OK != result) {
                Toast.makeText(JoinMeetActivity.this, "初始化引擎失败：" + result, Toast.LENGTH_LONG).show();
            } else {
                AVDEngine.instance().getRoomByRoomId(roomId);   // 初始化引擎成功后获取房间，会触发异步回调 AVDEngineListener.onGetRoomResult
            }
        }

        @Override
        public void onUninitResult(int reason) {

        }

        @Override
        public void onGetRoomResult(int result, RoomInfo room) {
            switch (result) {
                case 0:
                    joinRoom(); // 房间存在，直接加会
                    break;
                case 404:
                    /* 房间不存在，创建房间会触发异步回调 AVDEngineListener.onScheduleRoomResult */
                    AVDEngine.instance().scheduleRoom(new RoomInfo(roomId, true, userName));
                    break;
                default:
                    Toast.makeText(JoinMeetActivity.this, "获取房间失败：" + result, Toast.LENGTH_LONG).show();
                    break;
            }
        }

        @Override
        public void onFindRoomsResult(int result, List<RoomInfo> rooms) {

        }

        @Override
        public void onScheduleRoomResult(int result, String roomId) {
            switch (result) {
                case 0:
                    joinRoom(); // 创建房间成功，执行加入房间操作
                    break;
                default:
                    Toast.makeText(JoinMeetActivity.this, "创建房间失败：" + result, Toast.LENGTH_LONG).show();
                    break;
            }
        }

        @Override
        public void onCancelRoomResult(int result, String roomId) {

        }

        @Override
        public void onCallOutgoingDeviceResult(int result, String userId) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (AVDEngine.instance().isWorking()) {
            AVDEngine.instance().uninit();  // 注销引擎
        }
        Process.killProcess(Process.myPid());   // 关闭当前进程
    }
}
