import { CLConfigureUtil } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/CLConfigureUtil&1.0.0";
import camreManager from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/clliving/CLCamreManager&1.0.0";
import abilityAccessCtrl from "@ohos:abilityAccessCtrl";
import type { Permissions } from "@ohos:abilityAccessCtrl";
import camera from "@ohos:multimedia.camera";
import type photoAccessHelper from "@ohos:file.photoAccessHelper";
import { CLImageManager } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLImageManager&1.0.0";
import type image from "@ohos:multimedia.image";
import { CLRealPersonNetManager, CLRPNetResult, CLRPNetFaceResult, CLRPVedioResult } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/clliving/CLRealPersonNetManager&1.0.0";
import CLDispatchQueue from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLDispatchQueue&1.0.0";
import systemDateTime from "@ohos:systemDateTime";
import { CLVideoManager } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLVideoManager&1.0.0";
import CLLog from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLLogUtils&1.0.0";
// 设置检测时脸离屏幕距离，默认0（-1：稍近，0：正常，1：稍远）
export enum CLDistanceLevel {
    CLDistanceLevelNearbyMore = -2,
    CLDistanceLevelNearby = -1,
    CLDistanceLevelDefault = 0,
    CLDistanceLevelFar = 1,
    CLDistanceLevelFarMore = 2
}
/**
 * 安全等级
 */
export enum CLSecurityLevel {
    CLSecurityLevelLow = 0,
    CLSecurityLevelHigh = 1
}
/**
 * 安全等级
 * */
export enum CLStatus {
    CLCheckPass = 1,
    CLCheckNotPass = //活体检测不通过
     2,
    CLOperationTimeout = //操作超时，用户未在规定时间内完成动作
     3,
    CLGetConfFaild = //获取配置信息失败
     4,
    CLRecordFaild = //视频录制失败
     5,
    CLOnlineCheckFaild = //请求检测结果失败
     6,
    CLOnlineUploadFaild = //上传图片失败
     7,
    CLSDKError = //SDK内部发生错误
     8,
    CLRPVedioNoMate = //人脸动作与提示动作不吻合，请重试
     9,
    CLRPVedioNoFace = //没有检测到人脸，请重试
     10,
    CLRPVedioMoreFace = //检测到有多张人脸，请重试
     11,
    CLRPVideoIllumination = //检测到光线不足，请重试
     12,
    CLRPVedioAngle = //检测到人脸角度有偏差，请重试
     13,
    CLRPVedioBlue = //检测到人脸模糊，请重试
     14,
    CLRPVedioMask = //检测到人脸有遮挡，请重试
     15,
    CLRPVedioSmall = //检测到人脸过于靠近屏幕，请重试
     16,
    CLNetError = //无网络链接
     17,
    CLRPNoMoney = //账号余额不足
     18,
    CLRPVedioError = //其他错误
     19
}
/** @说明        检测中相关回调相关格式：
 {
 type = @"1";
 result = @"1";
 }
 内容说明：
 @"type" @"result"                   参考提示：
 @"1"    @"1"      人脸符合检测要求  -请保持姿势不变
 @"1"    @"2"      无人脸          -请面向屏幕
 @"1"    @"3"      人脸不全         -请保持脸在检测框内
 @"1"    @"4"      人脸占比过小     -请靠近一点
 @"1"    @"5"      光线暗          -当前光线过暗，请调整
 @"1"    @"6"      人脸模糊        -当前光线模糊，请调整
 @"1"    @"7"      人脸有遮挡      -请露出全脸
 @"1"    @"8"      其他错误        -其他错误，请继续
 @"3"    @"1"      检测中
 @"4"    @"url"    本地录制活体视频url(供转发用)

 number为动作总的数量
 type为2 result为-1时index表示将要执行的动作内容
 result不为-1时result表示将要执行的动作内容 index：表示动作的索引从0开始
 @"type" @"result" @"number" @“index”
 @"2"    @"-1"       @"3"     @"0"       准备开始3个动作（3为随机数字），（0表示）第一个为眨眼
 @"2"    @"0"        @"3"     @"1"       眨眼（index为动作索引）
 @"2"    @"4"        @"3"     @"1"       抬头（index为动作索引）
 @"2"    @"5"        @"3"     @"1"       低头（index为动作索引）
 @"2"    @"6"        @"3"     @"1"       张嘴（index为动作索引）
 @"2"    @"7"        @"3"     @"1"       摇头（index为动作索引）
 */
export type CLCompletionHandler = (status: CLStatus, params: any) => void;
export type CLAcitionsHandler = (params: any, url?: string) => void;
export interface CLTypeParamObject {
    type: string;
    result: string;
    number: string;
    index: string;
}
export class CLRealPersonManager {
    private static instance: CLRealPersonManager | null = null;
    private intervalId: number | null = null;
    private timeout: number = 30;
    private actDuration: number = 2;
    private actNumber: number = 1;
    private distance: number = 0;
    private securityLevel: number = 0;
    private canChek: boolean = false;
    private finshProgress: boolean = false;
    private sessionId: string = '';
    private permissions: Array<Permissions> = [
        'ohos.permission.CAMERA',
        'ohos.permission.MICROPHONE',
        // 'ohos.permission.MEDIA_LOCATION',
        'ohos.permission.READ_IMAGEVIDEO',
        'ohos.permission.WRITE_IMAGEVIDEO',
    ];
    private actionsHandler?: CLAcitionsHandler;
    private completionHandler?: CLCompletionHandler;
    /**设置token*/
    static setToken(token: string) {
        CLConfigureUtil.setToken(token);
    }
    /**获取版本号*/
    static getSDKVersion() {
        return CLConfigureUtil.LivingSDKVersion;
    }
    static getInstance(): CLRealPersonManager {
        if (!CLRealPersonManager.instance) {
            CLRealPersonManager.instance = new CLRealPersonManager();
        }
        return CLRealPersonManager.instance;
    }
    /**初始化*/
    initWithRecordView(context: Context, surfaceId: string) {
        abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context, this.permissions)
            .then(async (permissionList) => {
            camreManager.setSceneMode(camera.SceneMode.NORMAL_PHOTO);
            await camreManager.initCamera(context, surfaceId, 1);
            setTimeout(async () => {
                camreManager.takePicture();
            }, 200);
        });
    }
    /**
     * 设置活体检测的超时时间（在开始活体检测之前设置)
     * @param timeout 请传入10-120范围内的时间值，单位s
     */
    setTimeoutInterval(timeout: number) {
        this.timeout = timeout;
        if (this.timeout < 10 || this.timeout > 120) {
            this.timeout = 30;
        }
        this.intervalId = setTimeout(() => {
            this.timeoutSel();
        }, this.timeout * 1000);
    }
    timeoutSel() {
        // 超时关闭
        CLDispatchQueue.main.async(() => {
            if (this.completionHandler && this.finshProgress === false) {
                CLLog.info('超时已关闭');
                this.finshProgress = true;
                this.completionHandler(CLStatus.CLOperationTimeout, {});
                camreManager.stopVideo();
                camreManager.releaseCamera();
            }
        });
    }
    /**
     * 设置活体检测每个动作的时长（在开始活体检测之前设置
     * @param duration 每个动作的时长（1-5s）
     */
    setActionDuration(duration: number) {
        if (duration > 5) {
            duration = 2;
        }
        if (duration < 1) {
            duration = 2;
        }
        this.actDuration = duration;
    }
    /**
     * 设置检测时脸离屏幕距离（在开始活体检测之前设置）
     * @param distanceLevel 默认0（-1：稍近，0：正常，1：稍远）
     */
    setDistanceNumber(distanceLevel: CLDistanceLevel) {
        this.distance = distanceLevel;
    }
    /**
     * 设置活体检测动作的个数（在开始活体检测之前设置，默认为1个动作);
     * @param number:动作的个数（1-3）
     * @param securityLevel:安全级别：默认为低（移动动作），高至少为两个动作(会修正number设置为1的数量)
     */
    setActionNumer(number: number, securityLevel: CLSecurityLevel) {
        if (number > 3) {
            number = 3;
        }
        if (number < 1) {
            number = 1;
        }
        if (securityLevel === CLSecurityLevel.CLSecurityLevelLow) {
            this.securityLevel = 0;
        }
        else {
            this.securityLevel = 1;
            if (number < 2) {
                number = 2;
            }
        }
        this.actNumber = number;
    }
    /**
     * 开始活体检测
     * @param actionsHandler  活体检测动作序列号的回调
     * @param completionHandler 活体检测结果的回调，结果状态见CLStatus枚举类型
     */
    async startLiveDetectWithActionsHandler(actionsHandler?: CLAcitionsHandler, completionHandler?: CLCompletionHandler) {
        if (this.timeout > 0) {
            this.setTimeoutInterval(this.timeout);
        }
        this.finshProgress = false;
        this.canChek = false;
        if (actionsHandler) {
            this.actionsHandler = actionsHandler;
        }
        if (completionHandler) {
            this.completionHandler = completionHandler;
        }
        camreManager.setSavePictureCallback(async (photoAsset: photoAccessHelper.PhotoAsset) => {
            if (this.finshProgress) {
                return;
            }
            CLLog.info(`活体检测-截取图片结果：${photoAsset.uri}`);
            CLDispatchQueue.main.async(async () => {
                const imgPixMap: image.PixelMap = await CLImageManager.uri2PixelMap(photoAsset.uri);
                CLRealPersonNetManager.liveWithImage([imgPixMap], this.distance, (netResult: CLRPNetResult, faceResult: CLRPNetFaceResult) => {
                    if (this.finshProgress) {
                        return;
                    }
                    // 1.请求失败
                    if (netResult === CLRPNetResult.Faild) {
                        camreManager.stopVideo();
                        if (this.completionHandler) {
                            this.completionHandler(CLStatus.CLOnlineCheckFaild, {});
                        }
                        return;
                    }
                    // 2.网络请求成功，失败原因
                    if (faceResult !== CLRPNetFaceResult.FaceSucess) {
                        if (this.actionsHandler) {
                            if (faceResult === CLRPNetFaceResult.FaceNoFace) {
                                this.actionsHandler({ 'type': '1', 'result': '2' });
                            }
                            else if (faceResult === CLRPNetFaceResult.FaceNoComp) {
                                this.actionsHandler({ 'type': '1', 'result': '3' }, photoAsset.uri);
                            }
                            else if (faceResult === CLRPNetFaceResult.FaceSmall) {
                                this.actionsHandler({ 'type': '1', 'result': '4' });
                            }
                            else if (faceResult === CLRPNetFaceResult.Illumination) {
                                this.actionsHandler({ 'type': '1', 'result': '5' });
                            }
                            else if (faceResult === CLRPNetFaceResult.Blur) {
                                this.actionsHandler({ 'type': '1', 'result': '6' });
                            }
                            else if (faceResult === CLRPNetFaceResult.Mask) {
                                this.actionsHandler({ 'type': '1', 'result': '7' });
                            }
                            else if (faceResult === CLRPNetFaceResult.Error) {
                                this.actionsHandler({ 'type': '1', 'result': '8' });
                            }
                        }
                        CLLog.info(`活体检测-图片校验失败:${JSON.stringify(faceResult)}`);
                        // 报错重新拍照请求
                        CLDispatchQueue.main.dispatchAfter(500, () => {
                            CLLog.info(`活体检测-重新获取图片...`);
                            camreManager.takePicture();
                        });
                    }
                    else {
                        const startIndex = systemDateTime.getUptime(0);
                        // 成功
                        if (this.actionsHandler) {
                            CLLog.info(`活体检测-图片检测成功`);
                            this.actionsHandler({ 'type': '1', 'result': '1' });
                        }
                        CLLog.info(`活体检测-开始获取随机动作...`);
                        // 获取动作码
                        let actNumber = this.actNumber >= 1 ? this.actNumber : 1;
                        CLRealPersonNetManager.getRandomCode(actNumber, this.securityLevel, async (netResult: CLRPNetResult, result?: [
                            string
                        ], sessionId?: string) => {
                            if (this.finshProgress) {
                                return;
                            }
                            if (netResult === CLRPNetResult.Faild) {
                                this.finshProgress = true;
                                if (this.completionHandler) {
                                    this.completionHandler(CLStatus.CLGetConfFaild, {});
                                }
                                return;
                            }
                            this.sessionId = sessionId ?? '';
                            const endIndex = systemDateTime.getUptime(0);
                            if (endIndex - startIndex > 1000) {
                                await camreManager.captureToRecordVideo();
                                this.performVideo(result!, 0);
                            }
                            else {
                                setTimeout(async () => {
                                    await camreManager.captureToRecordVideo();
                                    this.performVideo(result!, 0);
                                }, 1200 - endIndex + startIndex);
                            }
                        });
                    }
                });
            });
        });
    }
    /**
     * 活体检测，视频转发
     * @param urlString  视频转发之后URL或者startLiveDetectWithActionsHandler：返回的url
     * @param isReTran 表示是否转发，
     * YES：转发urlString参数值为转发后的url
     * NO：不转发urlString参数值为startLiveDetectWithActionsHandler：中返回的url
     */
    resultWithDetectUrl(urlString: string, isReTran: boolean) {
        //1. 网络判断
        //2. 正常检测
        CLLog.info(`活体检测-视频开始检测...`);
        CLRealPersonNetManager.verifyWithVedio(urlString, isReTran, this.sessionId, (netResult: CLRPNetResult, videoResult: CLRPVedioResult, parm: Record<string, any>) => {
            if (netResult === CLRPNetResult.Faild) {
                CLDispatchQueue.main.async(() => {
                    CLLog.info(`活体检测-视频检测结果：失败,videoResult=>${JSON.stringify(videoResult)} ${JSON.stringify(parm)}`);
                    if (this.completionHandler) {
                        if (videoResult === CLRPVedioResult.CLRPYVedioNoPass) {
                            this.completionHandler(CLStatus.CLCheckNotPass, { 'url': '' });
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioNoFace) {
                            this.completionHandler(CLStatus.CLRPVedioNoFace, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioMoreFace) {
                            this.completionHandler(CLStatus.CLRPVedioMoreFace, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVideoIllumination) {
                            this.completionHandler(CLStatus.CLRPVideoIllumination, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioAngle) {
                            this.completionHandler(CLStatus.CLRPVedioAngle, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioBlue) {
                            this.completionHandler(CLStatus.CLRPVedioBlue, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioMask) {
                            this.completionHandler(CLStatus.CLRPVedioMask, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioSmall) {
                            this.completionHandler(CLStatus.CLRPVedioSmall, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioOnLineError) {
                            this.completionHandler(CLStatus.CLOnlineCheckFaild, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioNoMoney) {
                            this.completionHandler(CLStatus.CLRPNoMoney, {});
                        }
                        else if (videoResult === CLRPVedioResult.CLRPYVedioError) {
                            this.completionHandler(CLStatus.CLRPVedioError, {});
                        }
                    }
                });
                return;
            }
            // 检测正常结果
            CLDispatchQueue.main.async(() => {
                CLLog.info(`活体检测-视频检测结果：成功,videoResult=>${JSON.stringify(videoResult)} ${JSON.stringify(parm)}`);
                if (this.completionHandler) {
                    if (videoResult === CLRPVedioResult.CLRPYVedioPass) {
                        this.completionHandler(CLStatus.CLCheckPass, parm);
                    }
                    if (videoResult === CLRPVedioResult.CLRPYVedioNoPass) {
                        this.completionHandler(CLStatus.CLCheckNotPass, parm);
                    }
                }
            });
        });
    }
    async dealVideoResult(url: string) {
        // 输出类型为视频
        const videoUint8Array = await CLVideoManager.readVideo(url);
        if (!videoUint8Array || videoUint8Array.byteLength < 1) {
            CLDispatchQueue.main.async(() => {
                if (this.completionHandler) {
                    this.completionHandler(CLStatus.CLRecordFaild, { 'url': '' });
                }
            });
            return;
        }
        else {
            // 成功则返回
            if (this.actionsHandler) {
                this.actionsHandler({ 'type': '4', 'result': url });
            }
        }
    }
    performVideo(result: [
        string
    ], index: number) {
        if (this.finshProgress) {
            return;
        }
        if (index === 0) {
            CLDispatchQueue.main.async(() => {
                if (this.actionsHandler) {
                    this.actionsHandler({
                        'type': '2',
                        'result': '-1',
                        'number': `${result.length}`,
                        'index': result[0]
                    });
                }
            });
        }
        if (result && result.length > index) {
            CLDispatchQueue.main.async(() => {
                console.log(`当前的result是${result} ${index}`);
                if (this.actionsHandler) {
                    this.actionsHandler({ 'type': '2',
                        'result': `${result[index]}`,
                        'number': `${result.length}`,
                        'index': `${index}` });
                }
                index++;
                if (result.length <= index) {
                    this.canChek = true;
                }
                let actDuration = this.actDuration > 0.999 ? this.actDuration : 2.0;
                setTimeout(() => {
                    if (this.finshProgress) {
                        return;
                    }
                    this.performVideo(result, index);
                }, actDuration * 1000);
            });
        }
        else {
            if (this.canChek === false) {
                return;
            }
            this.finshProgress = true;
            CLDispatchQueue.main.async(() => {
                if (this.canChek === false) {
                    return;
                }
                if (this.actionsHandler) {
                    this.actionsHandler({
                        'type': '3',
                        'result': '1'
                    });
                }
            });
            // 结束录制，回调中查看结果
            camreManager.stopVideo().then(async (url: string) => {
                if (this.canChek === false) {
                    return;
                }
                console.log('输出的视频信息：' + url);
                const videoUint8Array = await CLVideoManager.readVideo(url);
                console.log('输出的视频信息：' + JSON.stringify(videoUint8Array));
                if (videoUint8Array && videoUint8Array.byteLength > 0) {
                    CLDispatchQueue.main.async(() => {
                        if (this.actionsHandler) {
                            this.actionsHandler({ 'type': '4', 'result': url });
                        }
                    });
                }
                else {
                    if (this.completionHandler) {
                        this.completionHandler(CLStatus.CLRecordFaild, { 'url': '' });
                    }
                }
            });
        }
    }
    /**
     * 停止活体检测,调用时机:
     * 1、在活体检测结果的回调里调用
     * 2、未完成活体检测，需要中止时调用 (超时不要调用)
     */
    stopLiveDetect() {
        this.finshProgress = true;
        camreManager.stopVideo();
        camreManager.releaseCamera();
        if (this.intervalId !== null) {
            clearInterval(this.intervalId);
            this.intervalId = null;
        }
    }
}
