package com.baidu.ai.sample;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import com.baidu.ai.sample.data.AIClientData;
import com.baidu.ai.sample.data.StartRequest;
import com.baidu.ai.sample.data.StartResponse;
import com.baidu.ai.sample.data.StopRequest;
import com.baidu.ai.sample.util.JavaTypesHelper;
import com.baidu.ai.sample.util.Utils;
import com.baidu.rtc.agent.AIAgentEngineCallback;
import com.baidu.rtc.agent.Constants;

import java.io.File;
import java.util.ArrayList;

public abstract class AiChatBaseActivity extends Activity {
    private static final String TAG = "AiChatBaseActivity";
    protected static final int REQUEST_IMAGE_CODE = 101;
    protected static final int REQUEST_TAKE_IMAGE_CODE = 102;

    protected static final int REQUEST_IMAGE_PREVIEW = 103;
    protected static final int REQUEST_TAKE_REFER_IMAGE_CODE = 104;

    protected AIController aiController;
    protected AIClientData mClientData;
    protected String fixedInstanceId;
    protected HttpClient mHttpClient;

    protected String mStartPath = HttpClient.START_PATH;
    protected String mStopPath = HttpClient.STOP_PATH;
    private Handler mMainHandler = new Handler();
    protected StartIntentResult mStartIntentResult;
    protected String mFuncCallSessionId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        window.requestFeature(Window.FEATURE_NO_TITLE);

        mStartIntentResult = new StartIntentResult(this);
        Intent intent = getIntent();
        if (intent.getExtras() != null) {
            mClientData = intent.getExtras().getParcelable("data");
            Log.i(TAG, "mClientData:" + mClientData.dumpString());
        }
    }

    protected void setupAgent() {
        mHttpClient = new HttpClient();
        aiController = new AIController();
        StartRequest mRequest = new StartRequest(mClientData.mAppId);

        if (!TextUtils.isEmpty(mClientData.mMode) && mClientData.mMode.equalsIgnoreCase(StartRequest.DH_TYPE)) {
            mRequest.instanceType = "DigitalHuman";
        }
        mRequest.addConfig(mClientData);

        String url = HttpClient.HOST + mStartPath;
        mHttpClient.asyncApiJsonBody(url, mRequest.toJson(), new HttpClient.Callback() {
            @Override
            public void onResponse(int code, String res) {
                if (code == HttpClient.HTTP_SUCCESS && !TextUtils.isEmpty(res)) {
                    StartResponse response = new StartResponse(res);
                    AIClientData data = new AIClientData();
                    data.mInstanceId = response.instanceId + "";

                    data.mMode = mClientData.mMode;
                    data.mContext = response.context;
                    data.mTokenStr = response.token;
                    data.mAppId = mClientData.mAppId;
                    data.mUserID = mClientData.mUserID;
                    data.mLicenseKey = mClientData.mLicenseKey;
                    data.mVoiceFpURL = mClientData.mVoiceFpURL;
                    data.mQueryEnhanceType = mClientData.mQueryEnhanceType;
                    data.mPreQuery = mClientData.mPreQuery;
                    data.mPostQuery = mClientData.mPostQuery;
                    data.mInterruptWords = mClientData.mInterruptWords;
                    data.mSense = mClientData.mSense;
                    data.mHintHistory = mClientData.mHintHistory;

                    onAIAgentGenerated(data.mInstanceId);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            aiController.onCreate(AiChatBaseActivity.this, data, mAgentCallback);
                            // 初始化RTCRoom
                            aiController.initRtcRoom();
                            // 初始化View
                            initAllViews();
                            // 登录房间
                            aiController.callAgent();
                        }
                    });
                }
            }
        });

    }

    protected void onAIAgentGenerated(String instanceId) {
        mClientData.mInstanceId = instanceId;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        /** 清除禁止熄屏 */
        Window window = getWindow();
        window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        mStartIntentResult.destroy();
        StopRequest request = new StopRequest(mClientData.mAppId, JavaTypesHelper.toLong(mClientData.mInstanceId, 1));
        String url = HttpClient.HOST + mStopPath;

        mHttpClient.asyncApiJsonBody(url, request.toJson(), new HttpClient.Callback() {
            @Override
            public void onResponse(int code, String res) {
                Log.i(TAG, "code:" + code + ",res:" + res);
            }
        });
        mHttpClient.onDestroy();
        if (aiController != null) {
            aiController.onDestroy();
        }
        if (mMainHandler != null) {
            mMainHandler.removeCallbacksAndMessages(null);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (aiController != null) {
            aiController.onResume();
        }
    }

    protected abstract void initAllViews();


    protected void hideInput(View view) {
        InputMethodManager inputMethodManager =
            (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager != null) {
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }
    }

    protected void onUIAIAgentSubtitle(String text, boolean isFinal) {
        Log.d(TAG, "onAIAgentSubtitle: " + text + ", isFinal:" + isFinal);
    }

    protected void onUIAsrSubtitle(String text, boolean isFinal, Constants.ASRExtInfo info) {
        Log.d(TAG, "onAsrSubtitle: " + text + ", isFinal:" + isFinal);
    }

    protected void addFileUploadBean(int imageUsageScenario, String path) {

    }

    protected void uploadFileStatus(int code, String msg) {
        if (code == Constants.NO_ERROR) {
            toastMsg("图片上传成功，可进行图片交互了！");
        }
    }

    protected void onAIAgentStateChange(int state) {
        if (state == Constants.CallState.ON_CALL_BEGIN) {
            toastMsg("Call Begin!");
        } else if (state == Constants.CallState.ON_CALL_END) {
            toastMsg("Call End!");
        }
    }

    protected String getASRExtInfo(Constants.ASRExtInfo info) {
        if (info == null) {
            return "";
        }

        return "{" +
                ", name:" + info.speakerName +
                ", score:" + info.similarity +
                ", emotion:" + info.emotion +
                "}";
    }
    private File mCaptureJPEGFile;
    private AIAgentEngineCallback mAgentCallback = new AIAgentEngineCallback() {

        @Override
        public void onCallStateChange(int state) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onAIAgentStateChange(state);
                }
            });
        }

        @Override
        public void onUserAsrSubtitle(String text, boolean isFinal, Constants.ASRExtInfo info) {
            if (TextUtils.isEmpty(text)) {
                return;
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onUIAsrSubtitle(text, isFinal, info);
                }
            });
        }

        @Override
        public void onAIAgentSubtitle(String text, boolean isFinal) {
            if (TextUtils.isEmpty(text)) {
                return;
            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onUIAIAgentSubtitle(text, isFinal);
                }
            });
        }

        @Override
        public void onAgentIntent(String type, Bundle bundle) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onCaptureJPEGFile();
                }
            });
        }


        @Override
        public void onFunctionCall(String id, String funcName, String params) {
            mFuncCallSessionId = id;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onFuncCall(id, funcName, params);
                }
            });
        }

        @Override
        public void onMediaGenerateStart(long taskId, String query) {
            mMainHandler.postDelayed(() -> {
                mediaGenerateStart(taskId, query);
            }, 500);
        }

        @Override
        public void onMediaGenerateCompleted(long taskId, int type, int error,
                                             ArrayList<Constants.MediaGenerateResult> resList,
                                             String msgRes) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    updateGenerateImage(taskId, type, error, msgRes, resList);
                }
            });
        }

        @Override
        public void onRecvTagMessage(String msg, boolean isFinal) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onCustomTagMessage(msg, isFinal);
                }
            });
        }

        @Override
        public void onUploadFileStatus(int code, String msg) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    uploadFileStatus(code, msg);
                }
            });
        }
    };


    protected void onCustomTagMessage(String msg, boolean isFinal) {

    }

    protected void mediaGenerateStart(long taskId, String query) {
    }

    protected void  onFuncCall(String id, String funcName, String params) {
        if (TextUtils.equals(funcName, "take_photo") || TextUtils.equals(funcName, "record_video")) {
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            mStartIntentResult.startActivityForResult(intent, REQUEST_IMAGE_PREVIEW);
        }
    }

    protected void updateGenerateImage(long taskId, int type, int error, String msgRes, ArrayList<Constants.MediaGenerateResult> resList) {
        Log.d(TAG, "updateGenerateImage type:" + type + ", error:" + error + ", resList:" + (resList != null ? resList.size() : "null"));
    }

    private void onCaptureJPEGFile() {
        try {
            File storageDir = new File(getFilesDir(), "images");
            if (!storageDir.exists()) {
                storageDir.mkdirs();
            }
            String imageFileName =  "Camera_" + System.currentTimeMillis() + ".jpeg";
            mCaptureJPEGFile = new File(storageDir, imageFileName);
            Log.i(TAG, "captureJPEGFile origin , " + mCaptureJPEGFile.getAbsolutePath());
            Uri photoUri = FileProvider
                    .getUriForFile(this, "com.baidu.ai.chat_demo.fileprovider", mCaptureJPEGFile);
            Log.i(TAG, "captureJPEGFile uri, " + photoUri);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            mStartIntentResult.startActivityForResult(intent, REQUEST_TAKE_IMAGE_CODE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void toastMsg(String msg) {
        Log.i(TAG, msg);

        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(AiChatBaseActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void uploadImage2(String path) {
        try {
            aiController.upload(Constants.ImageUsageScenario.VISION, path, 0);
            addFileUploadBean(Constants.ImageUsageScenario.VISION, path);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (!mStartIntentResult.checkResult(requestCode, resultCode, data)) {
            mStartIntentResult.clear();
            return;
        }
        if (requestCode == REQUEST_IMAGE_CODE || requestCode == REQUEST_TAKE_REFER_IMAGE_CODE) {
            if (resultCode == RESULT_OK && data != null) {
                String path = Utils.getAbsolutePath(this, data);
                if (!TextUtils.isEmpty(path) && aiController != null) {
                    int imageUsageScenario = requestCode == REQUEST_TAKE_REFER_IMAGE_CODE ?
                            Constants.ImageUsageScenario.IMAGE_GENERATE :
                            Constants.ImageUsageScenario.VISION;
                    // 3分钟超时
                    aiController.upload(imageUsageScenario, path, 180);
                    addFileUploadBean(imageUsageScenario, path);
                }
                Log.i(TAG, "onActivityResult uri:" + data.getData().toString() + ",path:" + path + ",intent:" + data);
            } else {
                Toast.makeText(AiChatBaseActivity.this, "取消", Toast.LENGTH_SHORT).show();
            }
            mStartIntentResult.clear();
            return;
        }

        if (requestCode == REQUEST_TAKE_IMAGE_CODE) {
            if (resultCode == RESULT_OK) {
                if (mCaptureJPEGFile != null) {
                    uploadImage2(mCaptureJPEGFile.getAbsolutePath());
                    Log.i(TAG, "take picture absolutePath," + mCaptureJPEGFile.getAbsolutePath());
                    mCaptureJPEGFile = null;
                }

            } else {
                Toast.makeText(AiChatBaseActivity.this, "取消", Toast.LENGTH_SHORT).show();
            }
            mStartIntentResult.clear();
            return;
        }

        if (requestCode == REQUEST_IMAGE_PREVIEW) {
            if (resultCode == RESULT_OK) {
                Log.i(TAG, "take picture preview success!");
            }
            mStartIntentResult.clear();
            return;
        }
        mStartIntentResult.clear();
    }
    static class StartIntentResult {
        public Intent intent;
        public int requestCode;
        public Activity mActivity;

        public StartIntentResult(Activity activity) {
            mActivity = activity;
        }

        public void startActivityForResult(Intent intent, int requestCode) {
            if (this.requestCode != 0 && this.intent != null) {
                Log.i(TAG, "startActivityForResult is Progress!, code:" + this.requestCode + ", intent:" + this.intent);
                return;
            }
            this.intent = intent;
            this.requestCode = requestCode;
            if (mActivity != null) {
                mActivity.startActivityForResult(intent, requestCode);
            }
        }

        public void clear() {
            this.intent = null;
            this.requestCode = 0;
        }

        public boolean checkResult(int requestCode, int resultCode, @Nullable Intent data) {
            Log.i(TAG, "checkResult, requestCode:" + requestCode + ", resultCode:" + resultCode + ", data:" + data);
            if (this.requestCode != 0 && this.requestCode == requestCode) {
                return true;
            }
            return false;
        }

        public void destroy() {
            Log.i(TAG, "StartIntentResult->destroy :" + this.requestCode + ", intent:" + this.intent);
            mActivity = null;
        }

    }
}