package xn.hxp.ui.verify.include;

import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.util.Size;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;

import com.blankj.utilcode.util.FileUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.ImageUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.SPUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.mlkit.vision.face.FaceDetection;
import com.google.mlkit.vision.face.FaceDetector;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import com.kongzue.dialogx.dialogs.PopTip;
import com.rc.httpcore.bean.UserValidationBean;
import com.rc.httpcore.client.HttpTool;
import com.rc.httpcore.vo.request.FaceCompare1Req;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

import kotlin.Triple;
import okhttp3.Response;
import xn.hxp.app.ChemicalApp;
import xn.hxp.databinding.FragmentFaceDetectBinding;
import xn.hxp.ui.plan.PlanAddData;
import xn.hxp.ui.plan.room.bean.locker.HxpCabinetDoorVo;
import xn.hxp.ui.verify.DoubleVerifyActivity;

public class FaceDetectView extends RelativeLayout {
    private FragmentFaceDetectBinding binding;
    private Context context;
    private LifecycleOwner lifecycleOwner;

    private FaceDetector faceDetector;
    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private Runnable providerFutureRunnable;
    private ProcessCameraProvider cameraProvider;
    private Preview preview;
    private ImageAnalysis imageAnalyzer;
    private ImageCapture imageCapture;
    private ImageCapture.OutputFileOptions outputFileOptions;
    private File photoFile;
    private DoubleVerifyActivity.DoubleVerifyListener doubleVerifyListener;
    private List<Triple<Boolean, Boolean, Long>> doubleVerifyList;
    private PlanAddData planAddData;

    public FaceDetectView(Context context, LifecycleOwner lifecycleOwner, List<Triple<Boolean, Boolean, Long>> doubleVerifyList, PlanAddData planAddData, DoubleVerifyActivity.DoubleVerifyListener doubleVerifyListener) {
        super(context);
        this.planAddData = planAddData;
        this.context = context;
        this.lifecycleOwner = lifecycleOwner;
        this.doubleVerifyListener = doubleVerifyListener;
        this.doubleVerifyList = doubleVerifyList;
        init();
    }


    private void init() {
        binding = FragmentFaceDetectBinding.inflate(LayoutInflater.from(context));
        addView(binding.getRoot());
        FaceDetectorOptions options = new FaceDetectorOptions.Builder()
                .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
                .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
                .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
                .build();
        faceDetector = FaceDetection.getClient(options);
        cameraProviderFuture = ProcessCameraProvider.getInstance(context);
        if (null == providerFutureRunnable) {
            providerFutureRunnable = () -> {
                try {
                    cameraProvider = cameraProviderFuture.get();
                    // 预览用例
                    preview = new Preview.Builder().build();
                    preview.setSurfaceProvider(binding.previewView.getSurfaceProvider());
                    Size size = new Size(640, 480);
                    // 图像分析用例
                    imageAnalyzer = new ImageAnalysis.Builder()
                            .setTargetResolution(size)
                            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                            .build();
                    // 图像捕捉
                    imageCapture = new ImageCapture.Builder()
                            .setTargetResolution(size)
                            .setFlashMode(ImageCapture.FLASH_MODE_AUTO)
                            .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                            .build();
                    @SuppressLint("SdCardPath") String facePicPath = "/sdcard/DCIM";
                    FileUtils.createOrExistsDir(facePicPath);
                    photoFile = new File(facePicPath, "face.jpg");
                    outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();
                    // 选择摄像头
                    CameraSelector cameraSelector;
                    if (0 == SPUtils.getInstance().getInt("cameraSelector", 0)) {
                        cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA;
                    } else {
                        cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;
                    }
                    // 解绑之前的用例
                    cameraProvider.unbindAll();
                    // 绑定用例到相机
                    cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalyzer, imageCapture);
                    ThreadUtils.executeByCachedAtFixRate(simpleTask, 3, 3, TimeUnit.SECONDS);
                } catch (Exception e) {
                    LogUtils.e(Log.getStackTraceString(e));
                }
            };
        }
        cameraProviderFuture.addListener(providerFutureRunnable, ContextCompat.getMainExecutor(context));
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        recycleFaceDetect();
    }

    @SuppressLint("RestrictedApi")
    private void recycleFaceDetect() {
        // 释放相机资源
        if (cameraProvider != null) {
            cameraProvider.unbindAll();
            cameraProvider = null;

            // 释放 FaceAnalyzer
            if (imageAnalyzer != null) {
                imageAnalyzer.clearAnalyzer(); // 清除 Analyzer
                imageAnalyzer = null;
            }
        }
        if (null != faceDetector) {
            // 释放人脸检测器
            faceDetector.close();
            faceDetector = null;
        }
        if (null != providerFutureRunnable) {
            if (null != preview) {
                preview.onUnbind();
                preview = null;
            }
            if (null != cameraProviderFuture) {
                cameraProviderFuture.cancel(true);
            }
            cameraProviderFuture = null;
            providerFutureRunnable = null;
        }
        ThreadUtils.cancel(simpleTask);
    }

    /**
     * 每三秒拍照一次
     */
    ThreadUtils.SimpleTask<Object> simpleTask = new ThreadUtils.SimpleTask<Object>() {
        @Override
        public Object doInBackground() throws Throwable {
            imageCapture.takePicture(outputFileOptions, ContextCompat.getMainExecutor(context), new ImageCapture.OnImageSavedCallback() {
                @Override
                public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                    ThreadUtils.executeByCached(new ThreadUtils.SimpleTask<UserValidationBean>() {
                        @Override
                        public UserValidationBean doInBackground() throws Throwable {
                            FaceCompare1Req faceCompare1Req = new FaceCompare1Req();
                            List<HxpCabinetDoorVo> hxpCabinetDoorVoList = planAddData.getDoorList();
                            if (null != hxpCabinetDoorVoList) {
                                for (int i = 0; i < hxpCabinetDoorVoList.size(); i++) {
                                    HxpCabinetDoorVo hxpCabinetDoorVo = hxpCabinetDoorVoList.get(i);
                                    faceCompare1Req.getDoorIds().add(String.valueOf(hxpCabinetDoorVo.getDoorId()));
                                }
                            }
                            try {
                                Response response = HttpTool.checkUserFaceByPic1(photoFile, ChemicalApp.subjectId, faceCompare1Req);
                                if (response.isSuccessful()) {
                                    String json = response.body().string();
                                    JSONObject jsonObject = new JSONObject(json);
                                    int code = jsonObject.getInt("code");
                                    if (200 == code) {
                                        return GsonUtils.fromJson(jsonObject.getJSONObject("data").toString(), UserValidationBean.class);
                                    } else {
                                        PopTip.show(jsonObject.getString("message"));
                                    }
                                } else {
                                    PopTip.show(response.message());
                                }
                            } catch (IOException e) {
                                LogUtils.e(Log.getStackTraceString(e));
                            }
                            return null;
                        }

                        @Override
                        public void onSuccess(UserValidationBean result) {
                            if (null != result) {
                                // 是否是 全部柜门管理员、安全员、实验室负责人
                                boolean isAdmin = Boolean.TRUE.equals(result.getSafeUser()) || Boolean.TRUE.equals(result.getAdminUser()) || Boolean.TRUE.equals(result.getCabinetAdmin());
                                Triple<Boolean, Boolean, Long> first = doubleVerifyList.get(0);
                                Triple<Boolean, Boolean, Long> second = doubleVerifyList.get(1);
                                // 第一个人必须是登录人
                                if (!first.getFirst()) {
                                    if (!result.getUserId().equals(ChemicalApp.userData.getUserId())) {
                                        PopTip.show("请登录人验证!");
                                        return;
                                    }
                                }
                                // 第一个人是否已认证通过 第二个人未通过
                                if (!first.getFirst() && !second.getFirst()) {
                                    doubleVerifyList.set(0, new Triple<>(true, isAdmin, Long.valueOf(result.getUserId())));
                                }
                                if (first.getFirst() && !second.getFirst()) {
                                    //  至少一个人是管理员
                                    if (!first.getSecond() && !isAdmin) {
                                        PopTip.show("请联系柜门管理员、安全员、实验室负责人进行验证");
                                        return;
                                    }
//                                    // 重复的人
//                                    if (first.getThird() == Long.parseLong(result.getUserId())) {
//                                        PopTip.show("验证人不能相同!");
//                                        return;
//                                    }
                                    doubleVerifyList.set(1, new Triple<>(true, isAdmin, Long.valueOf(result.getUserId())));
                                }

                                ThreadUtils.cancel(simpleTask);
                                doubleVerifyListener.detect(DetectType.FACE_DETECT, ImageUtils.getBitmap(photoFile), result);
                            }
                        }
                    });
                }

                @Override
                public void onError(@NonNull ImageCaptureException exception) {
                    LogUtils.e(Log.getStackTraceString(exception));
                }
            });
            return null;
        }

        @Override
        public void onSuccess(Object result) {

        }
    };
}
