package com.baidu.ai.sample;

import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Address;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.baidu.ai.sample.data.AIClientData;
import com.baidu.ai.sample.util.LocationClient;
import com.baidu.ai.sample.util.Utils;

import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * login
 */
public class LoginActivity extends AppCompatActivity {
    private static final String TAG = "LoginActivity";
    private static final String CLOUD_RENDER = "cloudRender";
    private static final String DIGITAL_HUMAN = "digitalHuman";
    private static final String APPBUILDER_NEWS = "abNews";

    private static final boolean IS_DEV = BuildConfig.IS_DEV;

    private static final int REQUEST_CAMERA_PERMISSION_ID = 100;
    private static final int REQUEST_MIC_PERMISSION_ID = 101;
    private static final int REQUEST_STORAGE_WRITE_PERMISSION_ID = 102;

    // UI references.
    private EditText mInstanceIDView;
    private TextView mTipsView;

    private boolean mIsCameraPermission = false;
    private boolean mIsMicPermission = false;
    private String mIntentConfig;
    private LocationClient mLocation;
    private String mCityLocation;
    private String mCoordinate;

    // 增强query插入类型包括:不插入、前插、后插、前后双插
    public String mQueryEnhanceType;
    // 增强query前插文本
    public String mPreQuery;
    // 增强query后插文本
    public String mPostQuery;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
            finish();
            return;
        }
        setContentView(R.layout.activity_login);

        // Set up the login form.
        mInstanceIDView = findViewById(R.id.instanceId);

        int instanceId = Utils.getDeviceId();
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        try {
            mInstanceIDView.setText(prefs.getString("key_instance_id", String.valueOf(instanceId)));
        } catch (Exception e) {
            e.printStackTrace();
        }


        Button mSignInButton = (Button) findViewById(R.id.sign_in_button);
        mSignInButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {

                if (mInstanceIDView.getText().toString().isEmpty()) {
                    return;
                }

                if (!mayRequestPermissions()) {
                    Log.i(TAG, "no permissions!");
                    return;
                }

                attemptLogin();
                SharedPreferences.Editor editor = prefs.edit();
                editor.putString("key_instance_id", mInstanceIDView.getText().toString());
                editor.putString("key_channel_id", mInstanceIDView.getText().toString());

                editor.apply();
            }
        });
        if (IS_DEV) {
            setupRadioButton();
        }
        TextView tv = findViewById(R.id.brtc_version);
        if (tv != null) {
            tv.setText("version:" + com.baidu.rtc.config.Constraints.sdkVersion());
        }
        mLocation = new LocationClient(this, new LocationClient.Callback() {
            @Override
            public void onResult(int code, Address address, String cord) {
                if (code == 0) {
                    Log.i(TAG, "LocationClient, city:" + address.getLocality() + ", subLocation:" + address.getSubLocality() + ",");

                    String c1 = address.getLocality();
                    String c2 = address.getSubLocality();
                    if (!TextUtils.isEmpty(c1)) {
                        mCityLocation = c1;
                    }
                    if (!TextUtils.isEmpty(c2)) {
                        mCityLocation += c2;
                    }
                } else {
                    mCoordinate = cord;
                }
            }
        });
        mSignInButton.postDelayed(new Runnable() {
            @Override
            public void run() {
                mLocation.request(LoginActivity.this);
            }
        }, 1000);

        mTipsView = findViewById(R.id.brtc_tip);
        if (mTipsView != null) {
            String appId = prefs.getString("key_appid", getString(R.string.agent_default_app_id));
            mTipsView.setText("appId:" + appId);
        }
        checkIntent();
    }

    private boolean mayRequestPermissions() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            mIsMicPermission = true;
            return true;
        }

        requestCameraAndMicPermissions();
        if (mLocation != null && mLocation.checkPermission()) {
            return false;
        }
        mIsCameraPermission = checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
        mIsMicPermission = checkSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED;
        if (mIsCameraPermission &&  mIsMicPermission
                && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        return false;
    }

    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (mLocation != null && mLocation.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
            return;
        }
        if (requestCode == REQUEST_CAMERA_PERMISSION_ID || requestCode == REQUEST_MIC_PERMISSION_ID
                || requestCode == REQUEST_STORAGE_WRITE_PERMISSION_ID) {
            if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                mayRequestPermissions();
            }
        }
    }

    private void requestCameraAndMicPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (this.checkSelfPermission(Manifest.permission.RECORD_AUDIO)
                    != PackageManager.PERMISSION_GRANTED) {
                this.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},
                        REQUEST_MIC_PERMISSION_ID);
            }
            if (this.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        REQUEST_STORAGE_WRITE_PERMISSION_ID);
            }
            if (this.checkSelfPermission(Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                this.requestPermissions(new String[]{Manifest.permission.CAMERA},
                        REQUEST_CAMERA_PERMISSION_ID);
            }
        }
    }

    /**
     * Attempts to sign in or register the account specified by the login form.
     * If there are form errors (invalid email, missing fields, etc.), the
     * errors are presented and no actual login attempt is made.
     */
    private void attemptLogin() {

        // Reset errors.
        mInstanceIDView.setError(null);

        // Store values at the time of the login attempt.
        String userid = mInstanceIDView.getText().toString();

        boolean cancel = false;
        View focusView = null;


        // Check for a valid userid address.
        if (TextUtils.isEmpty(userid)) {
            mInstanceIDView.setError(getString(R.string.error_field_required));
            focusView = mInstanceIDView;
            cancel = true;
        }

        if (cancel) {
            // There was an error; don't attempt login and focus the first
            // form field with an error.
            if (focusView != null) {
                focusView.requestFocus();
            }
        } else {
            // Show a progress spinner, and kick off a background task to
            // perform the user login attempt.
            login();
        }
    }

    private void login() {
        // mic 无权限
        if (!mIsMicPermission) {
            Toast.makeText(LoginActivity.this,
                    " 缺少音频权限，无法使用通话功能", Toast.LENGTH_SHORT).show();
            return;
        }


        if (TextUtils.isEmpty(mInstanceIDView.getText().toString().trim())) {
            Toast.makeText(LoginActivity.this,
                    "userId 不能为空", Toast.LENGTH_SHORT).show();
            return;
        }

        Intent intent;
        AIClientData data = new AIClientData();
        // 读去缓存信息
        data.readCacheData(LoginActivity.this);
        data.mInstanceId = mInstanceIDView.getText().toString().trim();
        if (!TextUtils.isEmpty(mIntentConfig)) {
            data.parseIntent(this, mIntentConfig);
        }
        if (IS_DEV) {
            data.mLLMName = getLLMConfig();
            data.mLang = getLangConfig();
            if (TextUtils.equals(data.mLang, "zh")) {
                data.mSay = "你好呀，你来了!";
                if (TextUtils.isEmpty(data.mSense)) {
                    data.mSense = getSenseConfig();
                    data.mRole = "非常有趣的闲聊机器人小文";
                }
            } else if (TextUtils.equals(data.mLang, "en")) {
                data.mSay = "Hello! Welcome back.";
                if (TextUtils.isEmpty(data.mSense)) {
                    data.mSense = getSenseConfig();
                    data.mRole = "Xiaowen, a very interesting chatbot";
                }
            }
            data.mLocation = mCityLocation;
            data.mCoordinate = mCoordinate;
            if (TextUtils.equals(data.mLLMName, "LLMMathGPT")) {
                data.mLLMUrl = "https://atms-api-pre.100tal.com/openapi/mathat/voice/chat?sid=1tal_mpbba5191a9f0944c8a0579cdf06f4a80c";
            }
            Log.i(TAG, "llmName:" + data.mLLMName + ",lang:" + data.mLang + ",loc:" + data.mLocation + ", say:" + data.mSay);
        }

        getEnhanceQuery(data);

        Class<?> clazz = AiChatActivity.class;
        String agentMode = getMode();
        if (TextUtils.equals(agentMode, CLOUD_RENDER)) {
            clazz = AiCloudRenderActivity.class;
            data.mMode = CLOUD_RENDER;
        } else if (TextUtils.equals(agentMode, DIGITAL_HUMAN)) {
            clazz = AiDigitalHumanActivity.class;
            data.mMode = DIGITAL_HUMAN;
        } else if (TextUtils.equals(agentMode, APPBUILDER_NEWS)) {
            clazz = AiABNewsActivity.class;
            data.mMode = APPBUILDER_NEWS;
        }

        intent = new Intent(LoginActivity.this, clazz);
        intent.putExtra("data", data);

        startActivity(intent);
    }

    @Override
    public void onBackPressed() {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
            finishAfterTransition();
        } else {
            super.onBackPressed();
        }
    }

    private void setupRadioGroup(ArrayList<RadioButton> list) {
        for (RadioButton btn : list) {
            btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    if (b) {
                        for (RadioButton tt : list) {
                            if (tt != compoundButton) {
                                tt.setChecked(false);
                            }
                        }
                    }
                }
            });
        }
    }

    private void setupRadioButton() {
        RadioButton llm4T = findViewById(R.id.rb_llm_4t);
        RadioButton llm4TLatest = findViewById(R.id.rb_llm_4t_latest);
        RadioButton llm4TEB = findViewById(R.id.rb_llm_4t_eb);
        RadioButton llmSpeed = findViewById(R.id.rb_llm_speed);
        RadioButton llmDefault = findViewById(R.id.rb_llm_default);
        ArrayList<RadioButton> llmArrayList = new ArrayList<>(Arrays.asList(
                llm4T, llm4TLatest, llm4TEB, llmSpeed, llmDefault));

        setupRadioGroup(llmArrayList);

        RadioButton langEN = findViewById(R.id.rb_lang_en);
        RadioButton langJA = findViewById(R.id.rb_lang_ja);
        RadioButton langZH = findViewById(R.id.rb_lang_zh);
        ArrayList<RadioButton> langArrayList = new ArrayList<>(Arrays.asList(langEN, langJA, langZH));
        setupRadioGroup(langArrayList);

        RadioButton senseNull = findViewById(R.id.rb_sense_null);
        RadioButton senseIdiom = findViewById(R.id.rb_sense_idiom);
        RadioButton senseInterview = findViewById(R.id.rb_lang_interview);
        RadioButton senseEnglish = findViewById(R.id.rb_lang_english);
        RadioButton senseJest = findViewById(R.id.rb_lang_jest);
        ArrayList<RadioButton> senseArrayList = new ArrayList<>(Arrays.asList(senseNull, senseIdiom, senseInterview, senseEnglish, senseJest));
        setupRadioGroup(senseArrayList);



        RadioButton modeVoice = findViewById(R.id.rb_mode_voice);
        RadioButton modeCloudRender = findViewById(R.id.rb_mode_cloudrender);
        RadioButton modeDH = findViewById(R.id.rb_mode_digital);
        ArrayList<RadioButton> modeArrayList = new ArrayList<>(Arrays.asList(modeVoice,
                modeCloudRender, modeDH));
        setupRadioGroup(modeArrayList);

        LinearLayout llQueryEnhance = findViewById(R.id.ll_query_enhance);
        llQueryEnhance.setVisibility(View.GONE);
        Switch queryEnhance = (Switch) findViewById(R.id.rb_query_enhance);
        queryEnhance.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    llQueryEnhance.setVisibility(View.VISIBLE);
                } else {
                    llQueryEnhance.setVisibility(View.GONE);
                }
            }
        });
    }

    private String getLLMConfig() {
        RadioButton llm4T = findViewById(R.id.rb_llm_4t);
        RadioButton llm4TLatest = findViewById(R.id.rb_llm_4t_latest);
        RadioButton llm4TEB = findViewById(R.id.rb_llm_4t_eb);
        RadioButton llmSpeed = findViewById(R.id.rb_llm_speed);
        RadioButton llmDefault = findViewById(R.id.rb_llm_default);

        if (llm4T.isChecked()) {
            return "LLM4TN";
        } else if (llm4TLatest.isChecked()) {
            return "LLM4T";
        } else if (llm4TEB.isChecked()) {
            return "LLM_MIX_PRIOR_EB4T";
        } else if (llmSpeed.isChecked()) {
            return "LLMSpeedPro";
        } else if (llmDefault.isChecked()) {
            return "";
        }
        return "";
    }

    private String getLangConfig() {
        RadioButton langEN = findViewById(R.id.rb_lang_en);
        RadioButton langJA = findViewById(R.id.rb_lang_ja);
        RadioButton langZH = findViewById(R.id.rb_lang_zh);

        if (langEN.isChecked()) {
            return "en";
        } else if (langZH.isChecked()) {
            return "zh";
        } else if (langJA.isChecked()) {
            return "ja";
        }
        return "";
    }

    private String getSenseConfig() {
        RadioButton senseNull = findViewById(R.id.rb_sense_null);
        RadioButton senseIdiom = findViewById(R.id.rb_sense_idiom);
        RadioButton senseInterview = findViewById(R.id.rb_lang_interview);
        RadioButton senseEnglish = findViewById(R.id.rb_lang_english);
        RadioButton senseJest = findViewById(R.id.rb_lang_jest);

        if (senseNull.isChecked()) {
            return "";
        } else if (senseIdiom.isChecked()) {
            return "成语接龙";
        } else if (senseInterview.isChecked()) {
            return "模拟面试";
        } else if (senseEnglish.isChecked()) {
            return "英语口语老师";
        } else if (senseJest.isChecked()) {
            return "讲笑话";
        }
        return "";
    }

    private String getMode() {
        RadioButton modeVoice = findViewById(R.id.rb_mode_voice);
        RadioButton modeCloudRender = findViewById(R.id.rb_mode_cloudrender);
        RadioButton modeDH = findViewById(R.id.rb_mode_digital);

        if (modeVoice.isChecked()) {
            return "voice";
        } else if (modeCloudRender.isChecked()) {
            return CLOUD_RENDER;
        } else if (modeDH.isChecked()) {
            return DIGITAL_HUMAN;
        }
        return "";
    }

    private void getEnhanceQuery(AIClientData data) {
        Switch queryEnhance = findViewById(R.id.rb_query_enhance);
        if (queryEnhance.isChecked() && data != null) {
            data.mQueryEnhanceType =
                    ((EditText) findViewById(R.id.et_query_enhance_type)).getText().toString();
            data.mPreQuery =
                    ((EditText) findViewById(R.id.et_pre_query)).getText().toString();
            data.mPostQuery =
                    ((EditText) findViewById(R.id.et_post_query)).getText().toString();
        }

    }

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

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        checkIntent();
    }

    private void checkIntent() {
        Intent intent = getIntent();
        if (intent != null && intent.getExtras() != null) {
            Log.i(TAG, "checkIntent intent:" + intent + ", extras:" + intent.getExtras());
            Bundle bundle = intent.getExtras();
            try {
                JSONObject root = new JSONObject();
                String appid = bundle.getString("appid", "");
                if (!TextUtils.isEmpty(appid)) {
                    root.put(AIClientData.KEY_APP_ID, appid);
                    Log.i(TAG, "checkIntent appid:" + appid);

                    if (mTipsView != null) {
                        mTipsView.setText("appId:" + appid);
                    }
                }
                String userId = bundle.getString("user_id", "");
                if (!TextUtils.isEmpty(userId)) {
                    root.put(AIClientData.KEY_USER_ID, userId);
                    Log.i(TAG, "checkIntent user_id:" + userId);
                }

                String licenseKey = bundle.getString("license_key", "");
                if (!TextUtils.isEmpty(licenseKey)) {
                    root.put(AIClientData.KEY_LICENSE_KEY, licenseKey);
                    Log.i(TAG, "checkIntent license_key:" + licenseKey);
                }

                String words = bundle.getString("interruption_words", "");
                if (!TextUtils.isEmpty(words)) {
                    root.put(AIClientData.KEY_INTERRUPTION_WORDS, words);
                    Log.i(TAG, "checkIntent interruption_words:" + words);
                }

                String voiceFpUrl = bundle.getString("voice_fp_url", "");
                if (!TextUtils.isEmpty(voiceFpUrl)) {
                    Log.i(TAG, "checkIntent voice_fp_url, origin:" + voiceFpUrl);

                    byte[] decoded = Base64.decode(voiceFpUrl, Base64.DEFAULT);
                    String jsonStr = new String(decoded, StandardCharsets.UTF_8);
                    root.put(AIClientData.KEY_VOICE_FP_URL_KEY, jsonStr);
                    Log.i(TAG, "checkIntent voice_fp_url:" + jsonStr);
                }

                String hintHistory = bundle.getString("hint_history", "");
                if (!TextUtils.isEmpty(hintHistory)) {
                    Log.i(TAG, "checkIntent hint_history, origin:" + voiceFpUrl);

                    byte[] decoded = Base64.decode(hintHistory, Base64.DEFAULT);
                    String jsonStr = new String(decoded, StandardCharsets.UTF_8);
                    root.put(AIClientData.KEY_HINT_HISTORY_ID, jsonStr);
                    Log.i(TAG, "checkIntent hint_history:" + jsonStr);
                    try {
                        JSONObject json = new JSONObject(jsonStr);
                        String type = json.optString("hint_type", "");
                        Log.i(TAG, "checkIntent hint_history#type:" + type);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                String sceneRole = bundle.getString("scene_role", "");
                if (!TextUtils.isEmpty(sceneRole)) {
                    root.put(AIClientData.KEY_SCENE_ROLE_ID, sceneRole);
                    Log.i(TAG, "checkIntent scene_role:" + sceneRole);
                }

                if (root.length() > 0) {
                    mIntentConfig = root.toString();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}