package com.videogo.ui.login;

import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.DataSetObserver;
import android.os.Build;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;

import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
import com.google.gson.Gson;
import com.videogo.EzvizApplication;
import com.videogo.exception.BaseException;
import com.videogo.global.DemoConfig;
import com.videogo.global.GlobalKit;
import com.videogo.openapi.EZOpenSDK;
import com.videogo.ui.devicelist.EZDeviceListActivity;
import com.videogo.util.LocalInfo;
import com.videogo.util.LogUtil;

import java.util.List;

import ezviz.ezopensdk.BuildConfig;
import ezviz.ezopensdk.R;

import com.videogo.util.SpTool;
import com.videogo.global.ValueKeys;
import ezviz.ezopensdkcommon.common.RootActivity;
import static com.videogo.EzvizApplication.getOpenSDK;
import static com.videogo.constant.Constant.OAUTH_SUCCESS_ACTION;

public class MainActivity extends RootActivity {

    private final static String TAG = MainActivity.class.getSimpleName();
    private ServerAreasEnum mCurrentServerArea;
    private EditText mApiET;
    private EditText mAuthET;
    private EditText mAppKeyET;
    private EditText mAccessTokenET;
    private EditText mSpecifiedDeviceET;
    // token登录参数
    public static SdkInitParams mInitParams;
    // 萤石云账号登录参数
    private SdkInitParams mSdkInitParams;
    // 萤石账号登录成功回调广播
    private BroadcastReceiver mLoginResultReceiver;

    /**
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initUI();
        autoLogin();

        mAppKeyET.setText(DemoConfig.APPKEY_DEV);
        mAccessTokenET.setText(DemoConfig.TOKEN_DEV);
        mSpecifiedDeviceET.setText(DemoConfig.DEVICE_DEV);
    }

    /**
     * 通过AccessToken/tkToken进行体验
     */
    public void onClickStartExperience(View view) {
        if (checkLoginInfo()) {
            SdkInitParams sdkInitParams = SdkInitParams.createBy(mCurrentServerArea);
            sdkInitParams.appKey = getValidText(mAppKeyET.getText().toString());
            sdkInitParams.token = getValidText(mAccessTokenET.getText().toString());
            sdkInitParams.openApiServer = getValidText(mApiET.getText().toString());
            sdkInitParams.openAuthApiServer = getValidText(mAuthET.getText().toString());
            sdkInitParams.specifiedDevice = getValidText(mSpecifiedDeviceET.getText().toString());
            SdkInitTool.initSdk(getApplication(), sdkInitParams);
            new Thread(() -> {
                showLoginAnim(true);
                if (checkAppKeyAndAccessToken()) {
                    // 保存相关信息
                    SpTool.storeValue(ValueKeys.SDK_INIT_PARAMS, sdkInitParams.toString());
                    jumpToCameraListActivity();
                }
                showLoginAnim(false);
            }).start();
        }
    }

    /**
     * 通过萤石账号进行体验
     */
    public void onClickLoginByEzvizAccount(View view) {
        if (mCurrentServerArea == null || mCurrentServerArea.defaultOpenAuthAppKey == null) {
            showToast("Error occurred! Please try to use demo with appKey & accessToken.");
            return;
        }
        mSdkInitParams = SdkInitParams.createBy(mCurrentServerArea);
        mSdkInitParams.appKey = getValidText(mAppKeyET.getText().toString());
        mSdkInitParams.openApiServer = getValidText(mApiET.getText().toString());
        mSdkInitParams.openAuthApiServer = getValidText(mAuthET.getText().toString());
        /**
         * 国内使用萤石账号登录，一定要设置为false
         * 本Demo是accessToken和tkToken两种模式共存的，如果第一次使用了tkToken，第二次要用accessToken模式登录，需要将enableSDKWithTKToken重置为false
         */
        if (!mSdkInitParams.usingGlobalSDK) {
            EZOpenSDK.enableSDKWithTKToken(false);
        }
        SdkInitTool.initSdk(getApplication(), mSdkInitParams);
        registerLoginResultReceiver();
        getOpenSDK().openLoginPage();
    }

    public void jcTestClick(View view) {
        if (!GlobalKit.isJCTest) {
            return;
        }
        mCurrentServerArea = ServerAreasEnum.getAllServers().get(0);
        mAppKeyET.setText(DemoConfig.APPKEY_JC);
        mAccessTokenET.setText(DemoConfig.TOKEN_JC);
        mSpecifiedDeviceET.setText(DemoConfig.DEVICE_JC);
        mApiET.setText(mCurrentServerArea.openApiServer);
        mAuthET.setText(mCurrentServerArea.openAuthApiServer);
        onClickStartExperience(null);
    }

    /**
     * 跳转设备列表页面
     */
    private void jumpToCameraListActivity() {
        Intent toCameraListIntent = new Intent(getApplicationContext(), EZDeviceListActivity.class);
        startActivity(toCameraListIntent);
        finish();
    }

    @SuppressLint("UnspecifiedRegisterReceiverFlag")
    private void registerLoginResultReceiver() {
        if (mLoginResultReceiver == null) {
            mLoginResultReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    Log.i(TAG, "login success by h5 page");
                    unregisterLoginResultReceiver();
                    SpTool.storeValue(ValueKeys.SDK_INIT_PARAMS, mSdkInitParams.toString());
                    jumpToCameraListActivity();
                    finish();
                }
            };
            IntentFilter filter = new IntentFilter(OAUTH_SUCCESS_ACTION);
            // 添加版本兼容性判断
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// Android 8.0及以上
                registerReceiver(mLoginResultReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
            } else {
                registerReceiver(mLoginResultReceiver, filter);
            }
            Log.i(TAG, "registered login result receiver");
        }
    }

    private void unregisterLoginResultReceiver() {
        if (mLoginResultReceiver != null) {
            unregisterReceiver(mLoginResultReceiver);
            mLoginResultReceiver = null;
            Log.i(TAG, "unregistered login result receiver");
        }
    }

    private void initData() {
        SpTool.init(getApplicationContext());
        if (!loadLastSdkInitParams()) {
            loadDefaultSdkInitParams();
        }
        if (!TextUtils.isEmpty(mInitParams.appKey) && !TextUtils.isEmpty(mInitParams.token)) {
            SdkInitTool.initSdk(getApplication(), mInitParams);
        }
    }

    /**
     * 是否能获取到之前的初始化参数
     *
     * @return 是否能获取到之前的初始化参数
     */
    private boolean loadLastSdkInitParams() {
        String sdkInitParamStr = SpTool.obtainValue(ValueKeys.SDK_INIT_PARAMS);
        if (sdkInitParamStr != null) {
            mInitParams = new Gson().fromJson(sdkInitParamStr, SdkInitParams.class);
            return mInitParams != null && mInitParams.appKey != null;
        }
        return false;
    }

    /**
     * 设置默认参数
     */
    private void loadDefaultSdkInitParams() {
        mInitParams = SdkInitParams.createBy(null);
        mInitParams.appKey = DemoConfig.APPKEY_DEV;
        mInitParams.openApiServer = "https://open.ys7.com";
        mInitParams.openAuthApiServer = "https://openauth.ys7.com";
    }

    /**
     * 检查AccessToken是否有效
     */
    private void startCheckLoginValidity() {
        showLoginAnim(true);
        if (checkAppKeyAndAccessToken()) {
            jumpToCameraListActivity();
            finish();
        }
        showLoginAnim(false);
    }

    private String getValidText(String origin) {
        if (origin == null) {
            return null;
        }
        StringBuilder target = new StringBuilder();
        for (char ch : origin.toCharArray()) {
            if (ch == '\0' || ch == '\n' || ch == 160) {
                break;
            } else {
                target.append(ch);
            }
        }
        return target.toString();
    }


    private ViewGroup mLoginAnimVg = null;
    private boolean isShowLoginAnim = false;

    private void showLoginAnim(final boolean show) {
        if (mLoginAnimVg == null) {
            mLoginAnimVg = findViewById(R.id.vg_login_anim);
        }
        if (mLoginAnimVg == null) {
            return;
        }
        runOnUiThread(() -> {
            isShowLoginAnim = show;
            mLoginAnimVg.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
        });
    }

    /**
     * 获取上次sdk初始化的参数
     */
    private SdkInitParams getLastSdkInitParams() {
        String lastSdkInitParamsStr = SpTool.obtainValue(ValueKeys.SDK_INIT_PARAMS);
        if (lastSdkInitParamsStr == null) {
            return null;
        } else {
            return new Gson().fromJson(lastSdkInitParamsStr, SdkInitParams.class);
        }
    }

    /**
     * 通过调用服务接口判断AppKey和AccessToken且有效
     *
     * @return 是否依旧有效
     */
    private boolean checkAppKeyAndAccessToken() {
        boolean isValid = false;
        try {
            EzvizApplication.getOpenSDK().getDeviceList(0, 1);
            isValid = true;
        } catch (BaseException e) {
            e.printStackTrace();
            Log.e(TAG, "Error code is " + e.getErrorCode());
            int errCode = e.getErrorCode();
            String errMsg;
            switch (errCode) {
                case 400031:
                    errMsg = getApplicationContext().getString(R.string.tip_of_bad_net);
                    break;
                default:
                    errMsg = getApplicationContext().getString(R.string.login_expire) + "\n" + e.getErrorInfo().description;
                    break;
            }
            showToast(errMsg);
        }
        return isValid;
    }

    /**
     * 验证是否输入 AppKey 和 AccessToken
     */
    private boolean checkLoginInfo() {
        if (mAppKeyET.getText().toString().equals("")) {
            showToast("AppKey不能为空");
            return false;
        }
        if (mAccessTokenET.getText().toString().equals("")) {
            showToast("AccessToken不能为空");
            return false;
        }
        return true;
    }

    private void initUI() {
        // 设置服务器区域下拉框显示和监听
        Spinner areaServerSp = findViewById(R.id.sp_server_area);
        if (areaServerSp != null) {
            ServerAreasSpAdapter adapter = new ServerAreasSpAdapter(getApplicationContext(), ServerAreasEnum.getAllServers());
            areaServerSp.setAdapter(adapter);
            areaServerSp.setOnItemSelectedListener(mServerAreasOnItemCLickLister);
        }
        mAppKeyET = findViewById(R.id.et_app_key);
        mAccessTokenET = findViewById(R.id.et_access_token);
        mApiET = findViewById(R.id.et_api_url);
        mAuthET = findViewById(R.id.et_auth_server);
        mSpecifiedDeviceET = findViewById(R.id.et_specified_device);

        SdkInitParams sdkInitParams = getLastSdkInitParams();
        if (sdkInitParams != null) {
            mAppKeyET.setText(sdkInitParams.appKey);
            try {
                mAccessTokenET.setText(EZOpenSDK.getInstance().getEZAccessToken().getAccessToken());
                mApiET.setText(sdkInitParams.openApiServer);
                mAuthET.setText(sdkInitParams.openAuthApiServer);
                mSpecifiedDeviceET.setText(sdkInitParams.specifiedDevice);
            } catch (Exception e) {
                LogUtil.d(TAG, "failed to load AccessToken");
            }
            for (int position = 0; position < ServerAreasEnum.getAllServers().size(); position++) {
                if (sdkInitParams.serverAreaId == ServerAreasEnum.getAllServers().get(position).id) {
                    if (areaServerSp != null) {
                        areaServerSp.setSelection(position);
                    }
                }
            }
        }

        TextView sdkVerTv = findViewById(R.id.tv_sdk_ver);
        if (sdkVerTv != null) {
            sdkVerTv.setText("SDK Version: " + BuildConfig.VERSION_NAME);
        }

        // 为所有输入框设置清除按钮
        setupClearButton(mApiET);
        setupClearButton(mAuthET);
        setupClearButton(mAppKeyET);
        setupClearButton(mAccessTokenET);
        setupClearButton(mSpecifiedDeviceET);
    }

    /**
     * 为输入框设置清除按钮：有内容时显示，点击清除内容
     */
    @SuppressLint("ClickableViewAccessibility")
    private void setupClearButton(final EditText editText) {
        if (editText == null) return;
        final Drawable clearIcon = ContextCompat.getDrawable(this, R.drawable.login_ic_clear);
        if (clearIcon == null) return;
        clearIcon.setBounds(0, 0, clearIcon.getIntrinsicWidth(), clearIcon.getIntrinsicHeight());

        // 根据当前内容更新清除图标的显隐
        updateClearIcon(editText, clearIcon);

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
            @Override
            public void afterTextChanged(Editable s) {
                updateClearIcon(editText, clearIcon);
            }
        });

        editText.setOnFocusChangeListener((v, hasFocus) -> updateClearIcon(editText, clearIcon));

        editText.setOnTouchListener((v, event) -> {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                Drawable endDrawable = editText.getCompoundDrawables()[2];
                if (endDrawable != null) {
                    int iconLeft = editText.getWidth() - editText.getPaddingRight() - endDrawable.getIntrinsicWidth();
                    if (event.getX() >= iconLeft) {
                        editText.setText("");
                        return true;
                    }
                }
            }
            return false;
        });
    }

    private void updateClearIcon(EditText editText, Drawable clearIcon) {
        boolean show = editText.hasFocus() && editText.getText().length() > 0;
        editText.setCompoundDrawables(null, null, show ? clearIcon : null, null);
    }

    /**
     * 自动登录
     */
    private void autoLogin() {
        View view = findViewById(R.id.page_container);
        if (view != null) {
            view.post(() -> {
                if (TextUtils.isEmpty(mInitParams.appKey)) {
                    showToast("AppKey is empty!");
                    return;
                }
                LocalInfo localInfo = LocalInfo.getInstance();
                boolean isNotExistAccessToken = localInfo == null || localInfo.getEZAccesstoken() == null
                        || localInfo.getEZAccesstoken().getAccessToken() == null;
                boolean isNotExistTKToken = localInfo == null || localInfo.getEZAccesstoken() == null
                        || localInfo.getEZAccesstoken().getHttpToken() == null;
                if (isNotExistAccessToken && isNotExistTKToken) {
                    String tip = "AccessToken/TKToken is empty!";
                    LogUtil.i(TAG, tip);
                    return;
                }
                new Thread(() -> startCheckLoginValidity()).start();
            });
        }
    }

    private AdapterView.OnItemSelectedListener mServerAreasOnItemCLickLister = new AdapterView.OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            mCurrentServerArea = ServerAreasEnum.getAllServers().get(position);
            mApiET.setText(mCurrentServerArea.openApiServer);
            mAuthET.setText(mCurrentServerArea.openAuthApiServer);
            // 仅预置了appKey的区域才展示萤石账号登录按钮
            showEzvizAccountLoginTv(mCurrentServerArea.defaultOpenAuthAppKey != null);
            // 萤石测试将appKey代入，方便测试
            if (DemoConfig.EzvizTest.equals(mCurrentServerArea.areaName)) {
                mAppKeyET.setText(mCurrentServerArea.defaultOpenAuthAppKey);
                mAccessTokenET.setText("");
                mSpecifiedDeviceET.setText("");
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            showEzvizAccountLoginTv(false);
        }

        private void showEzvizAccountLoginTv(boolean show) {
            View loginTv = findViewById(R.id.tv_ezviz_account_login);
            loginTv.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
        }

    };

    private class ServerAreasSpAdapter implements SpinnerAdapter {

        private Context mContext;
        private List<ServerAreasEnum> mServerAreaArray;

        public ServerAreasSpAdapter(@NonNull Context context, @NonNull List<ServerAreasEnum> serverList) {
            mContext = context;
            mServerAreaArray = serverList;
        }

        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return getDropDownServerAreaItemView(position, convertView);
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public int getCount() {
            int cnt = 0;
            if (mServerAreaArray != null) {
                cnt = mServerAreaArray.size();
            }
            return cnt;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public boolean hasStableIds() {
            return false;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return getServerAreaItemView(position, convertView);
        }

        @Override
        public int getItemViewType(int position) {
            return 1;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        private View getServerAreaItemView(int position, View convertView) {
            TextView itemTv = (TextView) convertView;
            if (itemTv == null) {
                itemTv = new TextView(mContext);
                itemTv.setTextColor(ContextCompat.getColor(mContext, R.color.red));
                // dp转px(applyDimension的用途是根据当前数值单位和屏幕像素密度将指定数值转换为Android标准尺寸单位px)
                int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, mContext.getResources().getDisplayMetrics());
                itemTv.setHeight(height);
                itemTv.setGravity(Gravity.CENTER_VERTICAL);
            }
            itemTv.setText(mServerAreaArray.get(position).areaName);
            return itemTv;
        }

        private View getDropDownServerAreaItemView(int position, View convertView) {
            TextView itemTv = (TextView) getServerAreaItemView(position, convertView);
            itemTv.setGravity(Gravity.CENTER);
            return itemTv;
        }
    }

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

    @Override
    public void onBackPressed() {
        if (isShowLoginAnim) {
            showToast(getApplicationContext().getString(R.string.cancel_init_sdk));
            showLoginAnim(false);
        } else {
            super.onBackPressed();
        }
    }
}
