package ai.guiji.duix.sample.ui.activity;

import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SwitchCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;


import org.jivesoftware.smack.util.StringUtils;
import org.webrtc.PeerConnection;

import java.util.ArrayList;
import java.util.List;

import ai.guiji.duix.sample.R;
import ai.guiji.duix.sample.audio.AudioRecorder;
import ai.guiji.duix.sample.audio.FileUtils;
import ai.guiji.duix.sample.pojo.LastSessionInfo;
import ai.guiji.duix.sample.ui.activity.base.DUIXActivity;
import ai.guiji.duix.sample.ui.adapter.WavUrlAdapter;
import ai.guiji.duix.sample.util.HttpUtils;
import ai.guiji.duix.sdk.DUIXFactory;
import ai.guiji.duix.sdk.IMMessageFormat;

public class DisplayActivity extends DUIXActivity implements View.OnTouchListener, CompoundButton.OnCheckedChangeListener, WavUrlAdapter.WavClickListener, View.OnClickListener, AudioRecorder.AudioRecorderListener {


    String mMsg = "Debug box: <<<";

    TextView tv_console, tv_speak, tv_face_detect;
    Button btn_send, btn_break;
    SwitchCompat switch_asr, switch_microphone_mute, switch_debug, switch_face_detect;
    EditText et_input;
    View layout_wav_list, layout_sender, layout_bottom, debug_view;
    RecyclerView rv_wav;

    boolean faceDetect;
    AudioRecorder mAudioRecorder;           // 录音模块
    String mOutputPath;                     // wav路径
//    MediaPipeFaceDetect mFaceDetect;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_display);

        debug_view = findViewById(R.id.debug_view);
        tv_console = findViewById(R.id.tv_console);
        tv_speak = findViewById(R.id.tv_speak);
        tv_speak.setOnTouchListener(this);
        debug_view.setVisibility(mConfig.isDebug() ? View.VISIBLE : View.GONE);
        layout_bottom = findViewById(R.id.layout_bottom);
        if (!mConfig.isControlPanel()) {
            layout_bottom.setVisibility(View.GONE);
        }
        switch_asr = findViewById(R.id.switch_asr);
        switch_asr.setChecked(mConfig.isAsr());
        switch_asr.setOnCheckedChangeListener(this);
        switch_microphone_mute = findViewById(R.id.switch_microphone_mute);
        switch_microphone_mute.setChecked(false);
        switch_microphone_mute.setOnCheckedChangeListener(this);
        switch_debug = findViewById(R.id.switch_debug);
        switch_debug.setChecked(mConfig.isDebug());
        switch_debug.setOnCheckedChangeListener(this);
        switch_face_detect = findViewById(R.id.switch_face_detect);
        switch_face_detect.setChecked(faceDetect);
        switch_face_detect.setOnCheckedChangeListener(this);
        tv_face_detect = findViewById(R.id.tv_face_detect);
        btn_break = findViewById(R.id.btn_break);
        btn_break.setOnClickListener(this);

        layout_wav_list = findViewById(R.id.layout_wav_list);
        layout_sender = findViewById(R.id.layout_sender);
        rv_wav = findViewById(R.id.rv_wav);
        rv_wav.setLayoutManager(new LinearLayoutManager(mContext, RecyclerView.HORIZONTAL, false));
        if ("bot".equals(mConfig.getRobotMode())) {
            layout_wav_list.setVisibility(View.GONE);
        } else {
            // 非bot类型发wav的url
            List<WavUrlAdapter.WavInfo> wavList = new ArrayList<>();
            wavList.add(new WavUrlAdapter.WavInfo("wav1", "https://robot.guiji.ai/model/2021/11/08/8a96c9d20c5b4074bfa444bcf22eeb07.wav"));
            wavList.add(new WavUrlAdapter.WavInfo("wav2", "https://robot.guiji.ai/model/2021/11/08/6504259c5dd74671ab157a0f7390ec60.wav"));
            WavUrlAdapter adapter = new WavUrlAdapter(mContext, wavList, this);
            rv_wav.setAdapter(adapter);
        }

        // 0: 一句话， 1: 长连接
        if (mConfig.getAsrMode() == 0) {
            tv_speak.setVisibility(View.VISIBLE);
            switch_asr.setVisibility(View.GONE);
        } else {
            tv_speak.setVisibility(View.GONE);
            switch_asr.setVisibility(View.VISIBLE);
        }

        fullscreen_renderer = findViewById(R.id.fullscreen_renderer);
        small_renderer = findViewById(R.id.small_renderer);
        btn_send = findViewById(R.id.btn_send);
        btn_send.setOnClickListener(this);
        et_input = findViewById(R.id.et_input);

//        mFaceDetect = new MediaPipeFaceDetect(mContext, faceCount -> runOnUiThread(() -> {
//            tv_face_detect.setText("Count: " + faceCount);
//            if (faceDetect) {
//                requestNextImage();
//            }
//        }));
        requestPermission();
    }

    private void appendMsg(String message) {
        Log.e(TAG, message);
        runOnUiThread(() -> {
            mMsg = message + "\n" + mMsg;
            tv_console.setText(mMsg);
        });
    }

//    // renderer获取位图
//    private void requestNextImage() {
//        if (local_renderer != null) {
//            // 该回调只会触发一次
//            local_renderer.addFrameListener(bitmap -> {
//                if (mFaceDetect != null) {
//                    mFaceDetect.faceDetect(bitmap);
//                }
//            }, 1.0F);
//        }
//    }

    @Override
    protected void permissionOk() {
        super.permissionOk();
        initDUIX();
    }

    String mLastSessionFlowId = "";
    String mLastSessionNodeId = "";

    @Override
    protected void connected() {
        runOnUiThread(() -> {
            // 查找上次会话最后停留的点如果找到并且robotCode一致就直接让数字人从该话术节点开始
            LastSessionInfo lastSessionInfo = LastSessionInfo.get(mContext);

            if (mConfig.getAppId().equals(lastSessionInfo.appId) && StringUtils.isNotEmpty(lastSessionInfo.flowId) && StringUtils.isNotEmpty(lastSessionInfo.nodeId)) {
                new AlertDialog.Builder(DisplayActivity.this).setMessage(R.string.find_last_session_title).setPositiveButton(R.string.resume_last_session, (dialog, which) -> {
                    appendMsg("try last session");
                    mLastSessionFlowId = lastSessionInfo.flowId;
                    mLastSessionNodeId = lastSessionInfo.nodeId;
                    createSession();
                }).setNegativeButton(R.string.restart, (dialog, which) -> {
                    LastSessionInfo.clear(mContext);
                    createSession();
                }).setCancelable(false).create().show();
            } else {
                createSession();
            }
        });
    }

    private void createSession() {
        if (mDUIXCore != null) {
            UUID = IMMessageFormat.getRandomUUID();
            DUIXFactory.SessionOptions sessionOptions = new DUIXFactory.SessionOptions(UUID, mConfig.getToken(), mConfig.getAppId())
                    .setRobotMode(mConfig.getRobotMode())
                    .setGroupId(mConfig.getGroupId())
                    .setFlowId(mLastSessionFlowId)
                    .setNodeId(mLastSessionNodeId)
                    .setAsrEnable(mConfig.isAsr());
            DUIXFactory.RTCOptions rtcOptions = new DUIXFactory.RTCOptions()
                    .setAudioEnable(mConfig.getAsrMode() == 1)
                    .setVideoEnable(mConfig.isCamera());
            mDUIXCore.createSession(mContext, eglBaseContext, sessionOptions, rtcOptions);
        }
    }

    @Override
    protected void busy() {
        runOnUiThread(() -> {
            appendMsg(mContext.getString(R.string.robot_busy));
            Toast.makeText(mContext, R.string.robot_busy, Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    protected void renderState(String state, String dataJson) {
        appendMsg("renderState: " + state);
        if ("Show".equals(state)) {
            mDUIXCore.clientReady(UUID);
            // UI隐藏加载框
        }
    }

    @Override
    protected void command(String type, String flowId, String nodeId) {
        if ("Say".equals(type)) {
            LastSessionInfo.put(mContext, mConfig.getAppId(), flowId, nodeId);
        }
    }

    @Override
    protected void connectError(String msg) {
        appendMsg("im connect error: " + msg);
    }

    @Override
    protected void detectedSpeech(String asrText) {
        appendMsg("onDetectedSpeech: " + asrText);

        // asr识别到语音发送给后台,这里可以根据情况调用answer或command
        if (mDUIXCore != null) {
            if ("bot".equals(mConfig.getRobotMode())) {
                mDUIXCore.sendByBot(UUID, asrText);
            } else {
                mDUIXCore.sendByClient(UUID, asrText, "");
            }
        }
    }

    @Override
    protected void iceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
        appendMsg("onIceConnectionChange: " + iceConnectionState);
        // 网络异常
        if (iceConnectionState == PeerConnection.IceConnectionState.FAILED) {
            closeSession(getString(R.string.tip_network_error_close_session));
        }
    }

    private void stopVoice() {
        long diff = System.currentTimeMillis() - startTime;
        long delay = diff > 1000L ? 0L : 1000L;
        mHandler.postDelayed(() -> {
            if (mAudioRecorder != null) {
                appendMsg("end recording");
                mAudioRecorder.stopRecord();
            }
        }, delay);
    }

    long startTime;

    private void startVoice() {
        mHandler.post(() -> {
            startTime = System.currentTimeMillis();
            appendMsg("start recording");

            mAudioRecorder = AudioRecorder.getInstance(this.getApplicationContext());
            mAudioRecorder.setListener(this);

            String name = FileUtils.createFileName("");
            mAudioRecorder.createDefaultAudio(name);
            mOutputPath = FileUtils.getWavFileAbsolutePath(mContext, name);
            mAudioRecorder.startRecord(null);
        });
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                tv_speak.setSelected(true);
                startVoice();
                break;
            case MotionEvent.ACTION_UP:
                tv_speak.setSelected(false);
                stopVoice();
                break;
            default:
                break;
        }
        return true;
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (buttonView == switch_asr) {
            mDUIXCore.asrSwitch(UUID, isChecked);
        } else if (buttonView == switch_microphone_mute) {
            mDUIXCore.setMicrophone(!isChecked);
        } else if (buttonView == switch_debug) {
            debug_view.setVisibility(isChecked ? View.VISIBLE : View.INVISIBLE);
        } else if (buttonView == switch_face_detect) {
//            faceDetect = isChecked;
//            if (faceDetect) {
//                requestNextImage();
//            } else {
//                tv_face_detect.setText("");
//            }
        }
    }

    @Override
    public void wavClick(String url) {
        if (mDUIXCore != null) {
            mDUIXCore.sendByClient(UUID, url);
            appendMsg("send wav url: " + url);
        }
    }

    // 根据不同的robotMode来决定用哪个接口发送消息
    private void sendIMMsg(String msg) {
        if ("bot".equals(mConfig.getRobotMode())) {
            // bot 模式直接传递文本
            mDUIXCore.sendByBot(UUID, msg);
        } else {
            mDUIXCore.sendByClient(UUID, msg, "");
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_send) {
            String msg = et_input.getText().toString();
            if ("".equals(msg)) {
                Toast.makeText(mContext, R.string.message_not_null, Toast.LENGTH_SHORT).show();
                return;
            }
            if (mDUIXCore != null) {
                sendIMMsg(msg);
                et_input.setText("");
                Toast.makeText(mContext, R.string.has_been_sent, Toast.LENGTH_SHORT).show();
                appendMsg("send msg: " + msg);
            }
        } else if (id == R.id.btn_break){
            if (mDUIXCore != null){
                mDUIXCore.audioBreak(UUID);
            }
        }
    }

    @Override
    public void onMakeWavComplete() {
        appendMsg("send recording: " + mOutputPath);
        HttpUtils.HttpResult result = HttpUtils.uploadFile(mOutputPath);
        if (result.code == 0) {
            appendMsg("send info: " + result.body);
            sendIMMsg(result.body);
        } else {
            appendMsg("send recording error: " + result.body);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            closeSession(null);
            //不执行父类点击事件
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mAudioRecorder != null) {
            mAudioRecorder.setListener(null);
            mAudioRecorder.release();
            mAudioRecorder = null;
        }
    }
}
