package com.viapidemo.faceverify;

import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;

import com.alipay.face.api.ZIMCallback;
import com.alipay.face.api.ZIMFacade;
import com.alipay.face.api.ZIMFacadeBuilder;
import com.alipay.face.api.ZIMResponse;
import com.aliyun.facebody20191230.Client;
import com.aliyun.facebody20191230.models.GenRealPersonVerificationTokenRequest;
import com.aliyun.facebody20191230.models.GenRealPersonVerificationTokenResponse;
import com.aliyun.facebody20191230.models.GetRealPersonVerificationResultRequest;
import com.aliyun.facebody20191230.models.GetRealPersonVerificationResultResponse;
import com.aliyun.facebody20191230.models.GetRealPersonVerificationResultResponseBody;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;

import java.security.MessageDigest;
import java.util.HashMap;

public class MainActivity extends Activity {

    private String TAG = "FaceVerifyTag";
    private String metaInfo = null;

    /*
      这个client是为了请求服务端接口，这里只是为了端上演示完整流程，所以将代码写在了Android端
      真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在端上，会有泄漏风险，建议将请求服务端接口代码写到您的服务端
     */
    private Client client = null;

    private ImageView bitmapImageView = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ZIMFacade.install(this);
        metaInfo = ZIMFacade.getMetaInfos(this);

        /*
          这个client是为了请求服务端接口，这里只是为了端上演示完整流程，所以将代码写在了Android端
          真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在端上，会有泄漏风险，建议将请求服务端接口代码写到您的服务端
         */
        try {
            // "YOUR_ACCESS_KEY_ID", "YOUR_ACCESS_KEY_SECRET" 的生成请参考https://help.aliyun.com/document_detail/175144.html
            // 如果您是用的子账号AccessKey，还需要为子账号授予权限AliyunVIAPIFullAccess，请参考https://help.aliyun.com/document_detail/145025.html
            Config config = new Config()
                    // 您的 AccessKey ID
                    .setAccessKeyId("YOUR_ACCESS_KEY_ID")
                    // 您的 AccessKey Secret
                    .setAccessKeySecret("YOUR_ACCESS_KEY_SECRET");
            config.endpoint = "facebody.cn-shanghai.aliyuncs.com";
            client = new Client(config);
        } catch (Exception e) {
            Log.e(TAG, String.format("onCreate: %s", e.getMessage()));
            showToastMsg("初始化失败");
        }

        bitmapImageView = findViewById(R.id.bitmap);
    }

    /**
     * 开始认证
     */
    public void beginVerify(View view) {
        String certName = ((EditText) findViewById(R.id.certName)).getText().toString();
        String certNo = ((EditText) findViewById(R.id.certNo)).getText().toString();

        if (TextUtils.isEmpty(certName) || TextUtils.isEmpty(certNo)) {
            showToastMsg("姓名&身份证必填");
            return;
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.d(TAG, String.format("beginVerify: %s %s %s", certName, certNo, metaInfo));
                    String verificationToken = callGenRealPersonVerificationToken(certName, certNo, metaInfo);
                    verify(verificationToken);
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.e(TAG, String.format("callGenRealPersonVerificationToken: %s", e.getMessage()));
                }
            }
        }).start();

    }

    /**
     * 进入认证
     * @param verificationToken 认证唯一标识
     */
    private void verify(String verificationToken) {
        HashMap<String, String> extParams = new HashMap<>();
        //如需指定活体检测UI界面方向(横屏)，请指定这一项。
        // extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_SCREEN_ORIENTATION, ZIMFacade.ZIM_EXT_PARAMS_VAL_SCREEN_LAND);
        //如需支持活体视频返回，请指定这一项，并在response.videoFilePath中获取视频本地路径。
        extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_USE_VIDEO, ZIMFacade.ZIM_EXT_PARAMS_VAL_USE_VIDEO_TRUE);
        //如需自定义活体检测页面的进度条颜色（默认可不设置），请设置此项，如红色 #FF0000。
        extParams.put(ZIMFacade.ZIM_EXT_PARAMS_KEY_FACE_PROGRESS_COLOR, "#FF0000");

        Log.d(TAG, String.format("verificationToken: %s", verificationToken));

        ZIMFacade zimFacade = ZIMFacadeBuilder.create(MainActivity.this);
        zimFacade.verify(verificationToken, true, extParams, new ZIMCallback() {
            @Override
            public boolean response(final ZIMResponse response) {
                Log.d(TAG, "端侧认证结果([" + response.code + "]" + response.reason + ")");
                if (1000 == response.code) {
                    Log.d(TAG, String.format("response.code: %s", response.code));
                    Log.d(TAG, String.format("response.reason: %s", response.reason));
                    Log.d(TAG, String.format("response.msg: %s", response.msg));
                    Log.d(TAG, String.format("response.deviceToken: %s", response.deviceToken));
                    Log.d(TAG, String.format("response.videoFilePath: %s", response.videoFilePath));
                    Log.d(TAG, String.format("response.bitmap: %s", "bitmap"));
                    Log.d(TAG, String.format("response.faceDectectAttr: %s", response.faceDectectAttr));
                    bitmapImageView.setImageBitmap(BitmapFactory.decodeByteArray(response.bitmap, 0, response.bitmap.length));
                }

                // 端侧认证结束后需要去服务端查询结果
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            GetRealPersonVerificationResultResponseBody.GetRealPersonVerificationResultResponseBodyData getRealPersonVerificationResultResponseBodyData = callGetRealPersonVerificationResult(verificationToken);
                            Log.d(TAG, String.format("getRealPersonVerificationResultResponseBodyData.pass: %s", getRealPersonVerificationResultResponseBodyData.getPassed()));
                            if(getRealPersonVerificationResultResponseBodyData.getPassed()) {
                                showToastMsg("认证通过");
                            } else {
                                showToastMsg("认证失败");
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            Log.e(TAG, String.format("callGetRealPersonVerificationResult: %s", e.getMessage()));
                        }
                    }
                }).start();

                return true;
            }
        });
    }

    /**
     * 调用GenRealPersonVerificationToken接口获取VerificationToken，可参考文档：https://help.aliyun.com/document_detail/198723.html
     * 这里只是为了端上演示完整流程，所以将代码写在了Android端
     * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在端上，会有泄漏风险，建议将请求服务端接口代码写到您的服务端
     * @param certificateName 被校验的身份证人名
     * @param certificateNumber 身份证号码
     * @param metaInfo metainfo环境参数，需要通过客户端SDK获取
     * @return
     */
    private String callGenRealPersonVerificationToken(String certificateName, String certificateNumber, String metaInfo) throws Exception {
        if(null == client) {
            throw new RuntimeException("client初始化失败");
        }
        GenRealPersonVerificationTokenRequest genRealPersonVerificationTokenRequest = new GenRealPersonVerificationTokenRequest();
        genRealPersonVerificationTokenRequest.setCertificateName(certificateName);
        genRealPersonVerificationTokenRequest.setCertificateNumber(certificateNumber);
        genRealPersonVerificationTokenRequest.setMetaInfo(metaInfo);
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            GenRealPersonVerificationTokenResponse genRealPersonVerificationTokenResponse = client.genRealPersonVerificationTokenWithOptions(genRealPersonVerificationTokenRequest, runtime);
            return genRealPersonVerificationTokenResponse.getBody().getData().getVerificationToken();
        } catch (com.aliyun.tea.TeaException teaException) {
            Log.d(TAG, "teaException.getCode(): " + teaException.getCode());
            if("InvalidAccessKeyId.NotFound".equals(teaException.getCode())) {
                showToastMsg("请求报错，请检查您代码中的YOUR_ACCESS_KEY_ID和YOUR_ACCESS_KEY_SECRET是否已经修改正确。");
            } else if("InvalidApi.NotPurchase".equals(teaException.getCode())) {
                showToastMsg("请求报错，您的账号未开通视觉智能开放平台-人脸人体，请进行开通：https://common-buy.aliyun.com/?commodityCode=viapi_facebody_public_cn#/open");
            } else if("Unauthorized".equals(teaException.getCode())) {
                showToastMsg("请求报错，您的子账号未授予AliyunVIAPIFullAccess权限，请参考https://help.aliyun.com/document_detail/145025.html");
            } else {
                showToastMsg(teaException.getMessage());
            }
            throw new Exception("请求GenRealPersonVerificationToken失败:" + teaException.getMessage());
        }
    }

    /**
     * 调用GetRealPersonVerificationResult接口获取认证结果，可参考文档：https://help.aliyun.com/document_detail/198724.html
     * 这里只是为了端上演示完整流程，所以将代码写在了Android端
     * 真正上线不建议将ACCESS_KEY_ID和ACCESS_KEY_SECRET写在端上，会有泄漏风险，建议将请求服务端接口代码写到您的服务端
     * @param verificationToken
     * @return
     * @throws Exception
     */
    private GetRealPersonVerificationResultResponseBody.GetRealPersonVerificationResultResponseBodyData callGetRealPersonVerificationResult(String verificationToken) throws Exception {
        if(null == client) {
            throw new Exception("client初始化失败");
        }
        GetRealPersonVerificationResultRequest getRealPersonVerificationResultRequest = new GetRealPersonVerificationResultRequest();
        getRealPersonVerificationResultRequest.setVerificationToken(verificationToken);
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            GetRealPersonVerificationResultResponse getRealPersonVerificationResultResponse = client.getRealPersonVerificationResultWithOptions(getRealPersonVerificationResultRequest, runtime);
            return getRealPersonVerificationResultResponse.getBody().getData();
        } catch (com.aliyun.tea.TeaException teaException) {
            showToastMsg(teaException.getMessage());
            throw new Exception("请求GetRealPersonVerificationResult失败:" + teaException.getMessage());
        }
    }

    /**
     * 显示toast
     * @param msg 内容
     */
    private void showToastMsg(final String msg) {
        if (TextUtils.isEmpty(msg)) {
            return;
        }

        if (Looper.getMainLooper() == Looper.myLooper()) {
            Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
        } else {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

}
