import { CLStringUtil, CLSecurityUtils, CLGzipUtil } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLSecurityUtils&1.0.0";
import { CLConfigureUtil } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/CLConfigureUtil&1.0.0";
import { compressedImage } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLImageCompressUtils&1.0.0";
import NetManager, { CLNetContanst } from "@normalized:N&&&@wanshu/realauthsdk/src/main/ets/utils/CLNetworkUtils&1.0.0";
import type { CLRealResult, CLRealImageVerifyResponse, CLRealRandomCodeResponse, CLRealVideoResultReponse } from './CLRealPersomResponse';
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";
import JSON from "@ohos:util.json";
export enum CLRPNetResult {
    Sucess = 0,
    Faild = 1
}
;
/**
 *  CLRPNetFaceResult
 * @param  FaceSucess 成功
 * @param FaceNoFace 无人脸
 * @param FaceNoComp 不在框内
 */
export enum CLRPNetFaceResult {
    FaceSucess = 0,
    FaceNoFace = 1,
    FaceNoComp = 2,
    FaceSmall = 3,
    Illumination = 4,
    Blur = 5,
    Mask = 6,
    Error = 7
}
;
export enum CLRPVedioResult {
    CLRPYVedioPass = 0,
    CLRPYVedioNoPass = 1,
    CLRPYVedioNoMate = 2,
    CLRPYVedioNoFace = 3,
    CLRPYVedioMoreFace = 4,
    CLRPYVideoIllumination = 5,
    CLRPYVedioAngle = 6,
    CLRPYVedioBlue = 7,
    CLRPYVedioMask = 8,
    CLRPYVedioSmall = 9,
    CLRPYVedioOnLineError = 10,
    CLRPYVedioNoMoney = 11,
    CLRPYVedioError = 12
}
;
export class CLRealPersonNetManager {
    private static __appId: string = '';
    private static __token: string = '';
    static async liveWithImage(images: [
        PixelMap
    ], distance: number, callback: (netResult: CLRPNetResult, faceResult: CLRPNetFaceResult) => void) {
        const pksId = CLConfigureUtil.getPksId();
        const pks = CLConfigureUtil.getPks();
        const random = CLStringUtil.generateRandomString(32).replace('-', '');
        const rsaRandomUUID = await CLSecurityUtils.encryptRSA(random, pks);
        const rsaRandomHex = CLStringUtil.uint8ArrayToHexString(rsaRandomUUID);
        let headers: Record<string, string> = {
            'Content-Encoding': 'gzip',
            'Content-Type': 'application/json',
            'Data-Key': (pksId + rsaRandomHex)
        };
        let imageArray = await Promise.all(images.map(async (img: PixelMap) => {
            const imageBuffer = await compressedImage(img, 1 * 1024);
            const imageData = await CLGzipUtil.gzipAndAES(imageBuffer, random);
            const imageBase64 = CLStringUtil.uint8ArrayToBase64(imageData);
            let params: Record<string, string> = {
                'image': imageBase64,
                'image_type': 'BASE64',
                'face_field': 'quality,location'
            };
            return params;
        }));
        let params: Record<string, any> = {
            'app_key': CLConfigureUtil.getAppId(),
            'auth_token': CLConfigureUtil.getToken(),
            'platform_type': CLConfigureUtil.getPlatform(),
            'images': imageArray
        };
        try {
            let r = await NetManager.post<CLRealResult<CLRealImageVerifyResponse>>(CLNetContanst.getPostFaceImage(), params, headers);
            cllog.info('截取图片识别请求结果' + JSON.stringify(r));
            if (r.code === '000000' && r.data.face_list.length > 0) {
                let faceModel = r.data.face_list[0];
                // 1.无人脸
                if (faceModel.quality && faceModel.quality.blur > 0.999) {
                    callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoFace);
                    return;
                }
                // 2.不在框内
                if (faceModel.quality && faceModel.quality.completeness === false) {
                    callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                    return;
                }
                // 3.光线暗
                if (faceModel.quality && faceModel.quality.illumination <= 40) {
                    callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Illumination);
                    return;
                }
                // 4. 遮挡
                if (faceModel.quality && faceModel.quality.occlusion) {
                    // 左眼被遮挡的阈值,模糊
                    if (faceModel.quality.occlusion.left_eye > 0.6) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 右眼被遮挡的阈值,模糊
                    if (faceModel.quality.occlusion.right_eye > 0.6) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 鼻子被遮挡的阈值,模糊
                    if (faceModel.quality.occlusion.nose > 0.7) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 嘴巴被遮挡的阈值,模糊
                    if (faceModel.quality.occlusion.mouth > 0.7) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 左脸被遮挡的阈值 0.8
                    if (faceModel.quality.occlusion.left_cheek > 0.8) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 右脸被遮挡的阈值 0.8
                    if (faceModel.quality.occlusion.right_cheek > 0.8) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                    // 下巴被遮挡的阈值 0.6
                    if (faceModel.quality.occlusion.chin_contour > 0.6) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Mask);
                        return;
                    }
                }
                // 5.距离
                if (faceModel.location) {
                    if (!images || images.length < 1) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                        return;
                    }
                    let image = images[0];
                    if (!image) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                        return;
                    }
                    const centerX = (image.getImageInfoSync().size.width / 2) ?? 320;
                    if (faceModel.location.width < (centerX - distance * 30) || faceModel.location.height < (centerX - distance * 30)) {
                        callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceSmall);
                        return;
                    }
                    if (faceModel.location.width > 0 && faceModel.location.height > 0) {
                        const width = faceModel.location.width;
                        const height = faceModel.location.height;
                        const ori = faceModel.location.rotation;
                        if (!images || images.length < 1) {
                            callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                            return;
                        }
                        let image = images[0];
                        if (!image) {
                            callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                            return;
                        }
                        const centerX = (image.getImageInfoSync().size.width / 2) ?? 320;
                        const centerY = (image.getImageInfoSync().size.height / 2) ?? 480;
                        console.log("检测异常时centerX:" + JSON.stringify(centerX) + "centerY:" + JSON.stringify(centerY) + "\n当前的数据" + JSON.stringify(faceModel.location));
                        const rrr = Math.sqrt(width * width + height * height) / 2;
                        const xxx = faceModel.location.left + rrr * (Math.cos(45 + ori / 360 * Math.PI));
                        const yyy = faceModel.location.top + rrr * (Math.sin(45 + ori / 360 * Math.PI));
                        const lefffft = Math.sqrt(((centerY - yyy) * (centerY - yyy) + (centerX - xxx) * (centerX - xxx)));
                        if (lefffft > centerX) {
                            callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceNoComp);
                            return;
                        }
                    }
                }
                // 6.
                if (faceModel.quality && faceModel.quality.completeness) {
                    callback(CLRPNetResult.Sucess, CLRPNetFaceResult.FaceSucess);
                    return;
                }
                callback(CLRPNetResult.Sucess, CLRPNetFaceResult.Error);
            }
            else {
                callback(CLRPNetResult.Faild, CLRPNetFaceResult.Error);
            }
        }
        catch (e) {
            callback(CLRPNetResult.Faild, CLRPNetFaceResult.Error);
            cllog.error('请求异常' + JSON.stringify(e));
        }
    }
    static async getRandomCode(number: number, securityLevel: number, callback: (netResult: CLRPNetResult, result?: [
        string
    ], sessionId?: string) => void) {
        let headers: Record<string, string> = {
            'Content-Type': 'application/json',
        };
        let params: Record<string, string | number> = {
            'actions_count': number,
            'platform_type': CLConfigureUtil.getPlatform(),
            'security_level': securityLevel,
            'app_key': CLConfigureUtil.getAppId(),
            'auth_token': CLConfigureUtil.getToken(),
        };
        try {
            let r = await NetManager.post<CLRealResult<CLRealRandomCodeResponse>>(CLNetContanst.getPostRandomCode(), params, headers);
            if (r.code === '000000') {
                if (r.data.actions) {
                    callback(CLRPNetResult.Sucess, r.data.actions, r.data.session_id);
                }
                else {
                    callback(CLRPNetResult.Faild, undefined, undefined);
                }
            }
            else {
                callback(CLRPNetResult.Faild, undefined, undefined);
            }
            cllog.info('获取动作code码请求结果' + JSON.stringify(r));
        }
        catch (e) {
            callback(CLRPNetResult.Faild, undefined, undefined);
            cllog.error('获取动作code码请求异常' + JSON.stringify(e));
        }
    }
    static async verifyWithVedio(base64StrOrUrl: string, isReTran: boolean, sessionId: string, callback: (netResult: CLRPNetResult, videoResult: CLRPVedioResult, parm: Record<string, any>) => void) {
        const pksId = CLConfigureUtil.getPksId();
        const pks = CLConfigureUtil.getPks();
        const random = CLStringUtil.generateRandomString(32).replace('-', '');
        const rsaRandomUUID = await CLSecurityUtils.encryptRSA(random, pks);
        const rsaRandomHex = CLStringUtil.uint8ArrayToHexString(rsaRandomUUID);
        let videoTmp = '';
        if (!base64StrOrUrl || base64StrOrUrl.length < 1) {
            callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioNoPass, {});
            return;
        }
        if (isReTran === false) {
            // 用户未上传，本地视频
            const videoUint8Array = await CLVideoManager.readVideo(base64StrOrUrl);
            if (!videoUint8Array || videoUint8Array.byteLength < 1) {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioNoPass, {});
                return;
            }
            const imageData = await CLGzipUtil.gzipAndAES(videoUint8Array, random);
            const imageBase64 = CLStringUtil.uint8ArrayToBase64(imageData);
            videoTmp = imageBase64;
        }
        else {
            // 用户上传，url链接
            const data = CLStringUtil.stringToUint8Array(base64StrOrUrl);
            const imageData = await CLGzipUtil.gzipAndAES(data, random);
            const imageBase64 = CLStringUtil.uint8ArrayToBase64(imageData);
            videoTmp = imageBase64;
        }
        let headers: Record<string, string> = {
            'Content-Encoding': 'gzip',
            'Content-Type': 'application/json',
            'Data-Key': (pksId + rsaRandomHex)
        };
        let video_type = isReTran ? 'URL' : 'BASE64';
        let params: Record<string, string> = {
            'video_type': video_type,
            'video': videoTmp,
            'session_id': sessionId,
            'app_key': CLConfigureUtil.getAppId(),
            'auth_token': CLConfigureUtil.getToken(),
            'platform_type': CLConfigureUtil.getPlatform()
        };
        try {
            let r = await NetManager.post<CLRealResult<CLRealVideoResultReponse>>(CLNetContanst.getPostFaceVideo(), params, headers);
            if (!callback) {
                return;
            }
            if (r.code === '000000') {
                if (r.data && r.data.action_verify) {
                    if (r.data.action_verify === 'pass') {
                        callback(CLRPNetResult.Sucess, CLRPVedioResult.CLRPYVedioPass, r.data);
                    }
                    else {
                        callback(CLRPNetResult.Sucess, CLRPVedioResult.CLRPYVedioNoPass, r.data);
                    }
                }
            }
            else if (r.code === '216434') {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioNoMate, {});
                return;
            }
            else if (r.code === '216501') {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioNoFace, {});
                return;
            }
            else if (r.code === '216507') {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioMoreFace, {});
                return;
            }
            else if (r.code === '216908') {
                if (r.error_msg && r.error_msg.includes('illumiantion')) {
                    callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVideoIllumination, {});
                }
                else if (r.error_msg && r.error_msg.includes('angle')) {
                    callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioAngle, {});
                }
                else if (r.error_msg && r.error_msg.includes('blur')) {
                    callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioBlue, {});
                }
                else if (r.error_msg && r.error_msg.includes('occlusion')) {
                    callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioMask, {});
                }
                else if (r.error_msg && r.error_msg.includes('too large')) {
                    callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioSmall, {});
                }
                return;
            }
            else if (r.code === '000318') {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioNoMoney, {});
            }
            else {
                callback(CLRPNetResult.Faild, CLRPVedioResult.CLRPYVedioError, {});
            }
            cllog.info('输出视频检验结果' + JSON.stringify(r));
        }
        catch (e) {
            cllog.error('输出视频检验请求异常' + JSON.stringify(e));
        }
    }
    static setToken(token: string) {
        CLRealPersonNetManager.__token = token;
    }
    static setAppId(appId: string) {
        CLRealPersonNetManager.__appId = appId;
    }
    getToken(): string {
        if (CLConfigureUtil.getToken()) {
            return CLConfigureUtil.getToken();
        }
        return CLRealPersonNetManager.__token;
    }
    getAppId(): string {
        if (CLConfigureUtil.getAppId()) {
            return CLConfigureUtil.getAppId();
        }
        return CLRealPersonNetManager.__appId;
    }
}
