//
//  QueenEngine.h
//  queen
//
//  Created by aliyun on 2021/3/14.
//  Copyright © 2021 alibaba-inc. All rights reserved.
//

#ifndef QueenEngine_H
#define QueenEngine_H

#import <Foundation/Foundation.h>
#import <CoreVideo/CoreVideo.h>
#import "QueenEngineConfigInfo.h"
#import <CoreMedia/CoreMedia.h>
#import <UIKit/UIKit.h>

@interface QEPixelBufferData : NSObject

/**
 * 需要处理的CVPixelBuffer。
 */
@property (nonatomic, assign) CVPixelBufferRef bufferIn;

/**
 * 处理完后的CVPixelBuffer。
 */
@property (nonatomic, assign) CVPixelBufferRef bufferOut;

/**
 * bufferIn中如果存在人脸/人体，人脸/人体顺时针旋转到正向所需要的角度，值为0/90/180/270，默认值为0。
 * 注意：仅当QueenEngineConfigInfo的autoSettingImgAngle设置为NO才会生效。
 */
@property (nonatomic, assign) size_t inputAngle;

/**
 * 识别到的正向人脸/人体结果需要逆时针旋转的角度，值为0/90/180/270，默认值为0。
 * 注意：仅当QueenEngineConfigInfo的autoSettingImgAngle设置为NO才会生效。一般情况下设置的值应该要和inputAngle一致，才会使得识别到的人脸/人体结果坐标位置和原图像贴合。
 */
@property (nonatomic, assign) size_t outputAngle;

/**
 * 识别到的人脸/人体结果坐标需要翻转的方向，默认值为kQueenBeautyFlipAxisNone。
 */
@property (nonatomic, assign) kQueenBeautyFlipAxis outputFlipAxis;

/**
 * 需要处理的CMSampleBuffer。
 */
@property (nonatomic, assign) CMSampleBufferRef sampleBufferIn;

@end

@interface QETextureData : NSObject

/**
 * 需要处理的OpenGL纹理ID。
 */
@property (nonatomic, assign) uint32_t inputTextureID;

/**
 * 处理完后的OpenGL纹理ID。
 */
@property (nonatomic, assign) uint32_t outputTextureID;

/**
 * OpenGL纹理的宽度。
 */
@property (nonatomic, assign) int width;

/**
 * OpenGL纹理的高度。
 */
@property (nonatomic, assign) int height;

@end

@interface QEGestureData : NSObject

/**
 * 手势类型。
 */
@property (nonatomic, assign) kQueenStaticGestureType gesture;

/**
 * 动态手势类型。
 */
@property (nonatomic, assign) kQueenHandActionType action;

@end

@interface QEFaceExpressionData : NSObject

/**
 * 脸部表情类型。
 */
@property (nonatomic, assign) kQueenFaceExpressionType expression;

@end

@interface QEAutoFaceShapeData : NSObject

/**
 * 智能美型当前状态。
 */
@property (nonatomic, assign) kQueenAutoFaceShapeStatus status;

/**
 * 围绕X轴旋转,也叫做俯仰角。
 */
@property (nonatomic, assign) float yaw;

/**
 * 围绕Y轴旋转,也叫偏航角。
 */
@property (nonatomic, assign) float pitch;

/**
 * 围绕Z轴旋转,也叫翻滚角。
 */
@property (nonatomic, assign) float roll;

@end

@interface QEFaceInfoItem : NSObject

/**
 * 人脸框坐标
 */
@property (nonatomic, assign) CGRect faceRect;

/**
 * 人脸欧拉角.
 */
@property (nonatomic, assign) QEYawPitchRoll faceYPR;

@end

@interface QEFaceInfoData : NSObject

/**
 * 监测到人脸的个数
 */
@property (nonatomic, assign) int faceCount;

/**
 * 每个人脸的相关信息
 */
@property (nonatomic, strong) NSArray<QEFaceInfoItem *> *faceInfoItems;

@end

@interface QEBodyInfoData : NSObject

@property (nonatomic, assign) int bodyPoseType;
@property (nonatomic, assign) int bodySportType;
@property (nonatomic, assign) int sportCount;

@end

@interface QEConcentrationDetectedItem : NSObject

@property (nonatomic, assign) kConcentrationType itemType;
@property (nonatomic, assign) float score;

@end

@interface QEConcentrationInfoData : NSObject

@property (nonatomic, assign) float score;
@property (nonatomic, strong) NSArray<QEConcentrationDetectedItem *> *detectedItems;
@property (nonatomic, assign) int faceNum;
@property (nonatomic, assign) int detectType;

@end

@interface QEAbnormalActionDetectedItem : NSObject

@property (nonatomic, assign) kAbnormalActionType itemType;
@property (nonatomic, assign) float score;

@end

@interface QEAbnormalActionInfoData : NSObject

@property (nonatomic, assign) float score;
@property (nonatomic, strong) NSArray<QEAbnormalActionDetectedItem *> *detectedItems;
@property (nonatomic, assign) int faceNum;
@property (nonatomic, assign) int detectType;

@end

@interface QELivingHumanDetectedItem : NSObject

@property (nonatomic, assign) kLivingHumanActionType itemType;
@property (nonatomic, assign) float score;

@end

@interface QELivingHumanInfoData : NSObject

@property (nonatomic, assign) float score;
@property (nonatomic, strong) NSArray<QELivingHumanDetectedItem *> *detectedItems;
@property (nonatomic, assign) int faceNum;
@property (nonatomic, assign) int detectType;

@end

@class QueenEngine;

@protocol QueenEngineDelegate <NSObject>

@optional

/**
 * 检测到手势的回调。
 * @param engine 引擎对象。
 * @param gestureData 手势数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectGesture:(QEGestureData *)gestureData;

/**
 * 检测到脸部表情的回调。
 * @param engine 引擎对象。
 * @param faceExpressionData 脸部表情数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectFaceExpression:(QEFaceExpressionData *)faceExpressionData;

/**
 * 检测到人脸信息的回调
 * @param engine 引擎对象
 * @param faceInfoData 人脸信息对象
 */
- (void)queenEngine:(QueenEngine *)engine didDetectFaceInfo:(QEFaceInfoData *)faceInfoData;

/**
 * 智能美型状态回调。
 * @param engine 引擎对象。
 * @param autoFaceShapeData 智能美型数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didChangeAutoFaceShapingStatus:(QEAutoFaceShapeData *)autoFaceShapeData;

/**
 * 检测到人体的回调。
 * @param engine 引擎对象。
 * @param bodyInfoData 人体数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectBodyInfo:(QEBodyInfoData *)bodyInfoData;

/**
 * 检测到人体的回调。
 * @param engine 引擎对象。
 * @param concentrationInfoData 人体数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectConcentrationInfo:(QEConcentrationInfoData *)concentrationInfoData;

/**
 * 检测到异常行为的回调。
 * @param engine 引擎对象。
 * @param abnormalActionInfoData 异常行为数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectAbnormalActionInfo:(QEAbnormalActionInfoData *)abnormalActionInfoData;

/**
 * 检测到活体信息的回调。
 * @param engine 引擎对象。
 * @param livingHumanInfoData 活体信息数据对象。
 */
- (void)queenEngine:(QueenEngine *)engine didDetectLivingHumanInfo:(QELivingHumanInfoData *)livingHumanInfoData;

@end

@interface QueenEngine : NSObject

/** QueenEngine回调代理对象。
 */
@property (nonatomic, weak) id <QueenEngineDelegate> delegate;

/**
 * 获取版本号。
 */
+ (NSString *)getVersion;

/**
 * 初始化引擎。
 * @param configInfo 配置信息。
 */
- (instancetype)initWithConfigInfo:(QueenEngineConfigInfo *)configInfo;

/**
 * 更新引擎配置参数。
 * 注意：仅当initWithConfigInfo的时候，configInfo为nil的时候此接口才生效，而且仅可设置一次有效值。
 * @param configInfo 配置信息。
 */
- (void)updateConfigInfo:(QueenEngineConfigInfo *)configInfo;

/**
 * 销毁引擎。
 * 注意：需要在渲染线程调用。
 */
- (void)destroyEngine;

/**
 * 高性能模式。
 * 注意：开启后效果会稍变差。
 * @param enabled YES/NO，默认NO。
 */
- (void)powerSavingEnabled:(BOOL)enabled;

/**
 * 设置渲染的viewport。
 * 注意：如果不设置默认使用输入的数据的宽和高。
 * @param originX 默认0
 * @param originY 默认0
 * @param width 默认0
 * @param height 默认0
 */
- (void)setScreenViewportWithOriginX:(int)originX withOriginY:(int)originY withWidth:(int)width withHeight:(int)height;

/**
 * 设置输出裁剪矩形。
 * 注意：如果不设置默认使用输入的数据的宽和高。
 * @param originX 默认0
 * @param originY 默认0
 * @param width 默认0
 * @param height 默认0
 */
- (void)setOutputRectWithOriginX:(int)originX withOriginY:(int)originY withWidth:(int)width withHeight:(int)height;

#pragma mark - "美颜类型和美颜参数API"

/**
 * 打开或者关闭某个功能效果。
 * @param type kQueenBeautyType 类型的一个值。
 * @param enabled YES: 打开，NO:关闭。
 */
- (void)setQueenBeautyType:(kQueenBeautyType)type enable:(BOOL)enabled;

/**
 * 打开或者关闭某个功能效果。
 * @param type kQueenBeautyType 类型的一个值。
 * @param enabled YES: 打开，NO:关闭。
 * @param mode kQueenBeautyFilterMode 类型的一个值。
 */
- (void)setQueenBeautyType:(kQueenBeautyType)type enable:(BOOL)enabled mode:(kQueenBeautyFilterMode)mode;

/**
 * 打开或者关闭某个功能效果。
 * @param type kQueenBeautyType 类型的一个值。
 * @param enabled YES: 打开，NO:关闭。
 * @param mode kQueenBeautyFilterMode 类型的一个值。
 * @param userInfo 预留字段。
 */
- (void)setQueenBeautyType:(kQueenBeautyType)type enable:(BOOL)enabled mode:(kQueenBeautyFilterMode)mode userInfo:(NSString *)userInfo;

/**
 * 设置功能参数。
 * @param param 功能参数类型，kQueenBeautyParams 中的一个。
 * @param value 需要设置的数值，参考kQueenBeautyParams的备注。
 */
- (void)setQueenBeautyParams:(kQueenBeautyParams)param value:(float)value;

/**
 * 获取功能参数。
 * @param param 功能参数类型，kQueenBeautyParams 中的一个。
 */
- (float)getQueenBeautyParams:(kQueenBeautyParams)param;

/**
 * 获取功能开启状态。
 * @param beautyType 功能类型，kQueenBeautyType 中的一个。
 */
- (BOOL)getQueenBeautyEnabledState:(kQueenBeautyType)beautyType;

#pragma mark - "滤镜相关API"

/**
 * 设置滤镜资源。
 * 注意：设置滤镜图片前需要将kQueenBeautyTypeLUT打开。
 * @param imagePath 所要设置的滤镜图片的地址。
 */
- (void)setLutImagePath:(NSString *)imagePath;

#pragma mark - "美型相关API"

/**
 * 设置美型参数。
 * 注意：设置前需要将kQueenBeautyTypeFaceShape打开。
 * @param faceShapeType 美型类型，kQueenBeautyFaceShapeType 中的一个。
 * @param value 需要设置的数值，参考kQueenBeautyFaceShapeType的备注。
 */
- (void)setFaceShape:(kQueenBeautyFaceShapeType)faceShapeType value:(float)value;

#pragma mark - "美体相关API"

/**
 * 设置美体参数。
 * 注意：设置前需要将kQueenBeautyTypeBodyShape打开。
 * @param bodyShapeType 美体类型，kQueenBeautyBodyShapeType 中的一个。
 * @param value 需要设置的数值，参考kQueenBeautyBodyShapeType的备注。
 */
- (void)setBodyShape:(kQueenBeautyBodyShapeType)bodyShapeType value:(float)value;

- (void)setBodyDetectSportType:(int)bodyDetectSportType;

- (void)clearBodySportCount;

#pragma mark - "美妆相关api"

/**
 * 设置美妆类型和图片素材路径。
 * 注意：设置前需要将kQueenBeautyTypeMakeup 打开。
 * @param makeupType 美妆类型，kQueenBeautyMakeupType 中的一个。
 * @param imagePaths 美妆素材地址集合。
 * @param blend 混合类型。
 */
- (void)setMakeupWithType:(kQueenBeautyMakeupType)makeupType paths:(NSArray<NSString *> *)imagePaths blendType:(kQueenBeautyBlend)blend;

/**
 * 设置美妆类型和图片素材路径。
 * 注意：设置前需要将kQueenBeautyTypeMakeup 打开。
 * @param makeupType 美妆类型，kQueenBeautyMakeupType 中的一个。
 * @param imagePaths 美妆素材地址集合。
 * @param blend 混合类型。
 * @param fps 对应的帧率
 */
- (void)setMakeupWithType:(kQueenBeautyMakeupType)makeupType paths:(NSArray<NSString *> *)imagePaths blendType:(kQueenBeautyBlend)blend fps:(int)fps;

/**
 * 设置美妆透明度，可指定性别。
 * @param makeupType 美妆类型。
 * @param isFeMale 是否是女性，女性:YES，男性:NO，（男性为接口预留，这里均传女性即YES即可）。
 * @param alpha 妆容透明度。
 */
- (void)setMakeupAlphaWithType:(kQueenBeautyMakeupType)makeupType female:(BOOL)isFeMale alpha:(float)alpha;

/**
 * 设置美妆类型的混合类型。
 * @param makeupType 美妆类型。
 * @param blend 混合类型。
 */
- (void)setMakeupBlendWithType:(kQueenBeautyMakeupType)makeupType blendType:(kQueenBeautyBlend)blend;

/**
 * 清除所有美妆。
 */
- (void)resetAllMakeupType;

#pragma mark - "头发美化相关API"

/**
 * 设置头发颜色。
 * 注意：设置前需要将kQueenBeautyTypeHairColor 打开。
 * @param red [0,1]
 * @param green [0,1]
 * @param blue [0,1]
 */
- (void)setHairColorWithRed:(float)red withGreen:(float)green withBlue:(float)blue;

#pragma mark - "贴纸相关API"

/**
 * 增加贴纸/贴图/实景抠图需要替换的背景，素材统一接口，支持GLTF,TAOPAI,MEDIAAI 类型。
 * @param materialPath 要添加的素材的路径。
 */
- (void)addMaterialWithPath:(NSString *)materialPath;

/**
 * 增加贴纸/贴图/实景抠图需要替换的背景，素材统一接口，支持GLTF,TAOPAI,MEDIAAI 类型。
 * @param materialPath 要添加的素材的路径。
 * @param zorder 贴纸顺序
 */
- (void)addMaterialWithPath:(NSString *)materialPath zorder:(int)zorder;

/**
 * 删除贴纸/贴图/实景抠图需要替换的背景。
 * @param materialPath 要删除的素材的路径。
 */
- (void)removeMaterialWithPath:(NSString *)materialPath;

#pragma mark - "抠图相关API"

/**
 * 绿幕/蓝幕抠图。
 * 注意：开启此抠图功能，纯色背景抠图（setPureColorToBackground）会关闭。
 * @param backgroundImagePath 需要绿/蓝幕替换的背景资源路径，传空即为取消抠图功能。
 * @param blueScreenEnabled 是否蓝幕抠图。
 * @param threshold 幕布敏感度[1,10]，默认1。
 * @param autoThresholdEnabled 是否根据环境动态计算幕布敏感度，为true时调节参数threshold失效，为false时调节参数threshold生效。
 */
- (void)setGreenScreen:(NSString *)backgroundImagePath blueScreenEnabled:(BOOL)blueScreenEnabled threshold:(float)threshold autoThresholdEnabled:(BOOL)autoThresholdEnabled;

/**
 * 绿幕/蓝幕抠图。
 * 注意：开启此抠图功能，纯色背景抠图（setPureColorToBackground）会关闭。
 * @param backgroundImagePath 需要绿/蓝幕替换的背景资源路径，传空即为取消抠图功能。
 * @param blueScreenEnabled 是否蓝幕抠图。
 * @param threshold 幕布敏感度[1,10]，默认1。
 * @param autoThresholdEnabled 是否根据环境动态计算幕布敏感度，为true时调节参数threshold失效，为false时调节参数threshold生效。
 * @param backgroundProcessType 背景处理方式。
 */
- (void)setGreenScreen:(NSString *)backgroundImagePath blueScreenEnabled:(BOOL)blueScreenEnabled threshold:(float)threshold autoThresholdEnabled:(BOOL)autoThresholdEnabled backgroundProcessType:(kQueenBackgroundProcessType)backgroundProcessType;

/**
 * 纯色背景抠图。
 * 注意：开启此抠图功能，绿幕抠图（setGreenScreen）会关闭。
 * @param backgroundImagePath 需要纯色背景替换的背景资源路径，传空即为取消抠图功能。
 * @param colorType 需要被替换的颜色类型，0绿色(green)，1蓝色(blue)，2青色(cyan)，3紫色(purple)，4黄色(yellow)，5红色(red)，默认0。
 * @param threshold 颜色敏感度[-1, 1], 默认0。
 */
- (void)setPureColorToBackground:(NSString *)backgroundImagePath colorType:(kQueenBeautyBgColorType)colorType threshold:(float)threshold;

/**
 * 实景抠像。
 * @param backgroundImagePath 需要替换的背景资源路径，传空即为取消抠图功能。
 * @param flipX 背景左右翻转。
 * @param flipY 背景上下翻转。
 */
- (void)setSegmentBackground:(NSString *)backgroundImagePath flipX:(BOOL)flipX flipY:(BOOL)flipY;

/**
 * 调整实景抠图的背景处理方式
 * @param backgroundProcessType 背景处理方式，默认为背景虚化
 */
- (void)setSegmentBackgroundProcessType:(kQueenBackgroundProcessType)backgroundProcessType;

/**
 * 设置实景抠像的性能模式。
 * 注意：在开启实景抠像功能前调用才能生效。
 * @param performanceMode 实景抠图的性能模式。
 */
- (void)setSegmentPerformanceMode:(kQueenSegmentPerformanceMode)performanceMode;

/**
 * 调整实景抠图的前景边距。
 * @param foregroundPadding 前景边距，[0,15]，默认0。
 */
- (void)setAISegmentForegroundPadding:(int)foregroundPadding;

#pragma mark - "互动相关API"

/**
 * AR写字/绘画。
 * @param enabled YES: 打开，NO:关闭。
 * @param mode 1: 写字, 2: 画画。
 */
- (void)setARWriting:(BOOL)enabled mode:(int)mode;

#pragma mark - "数据处理"

/**
 * 人脸识别信息和渲染是否翻转以Y轴方向翻转。
 * @param faceRenderFlipY 需要关键点确定位置的图像渲染时是否反转，默认NO。
 * @param faceInfoFlipY 关键点数据是否翻转，默认NO。
 */
- (void)setFaceRenderFlipY:(BOOL)faceRenderFlipY faceInfoFlipY:(BOOL)faceInfoFlipY;

/**
 * 处理PixelBuffer类型数据。
 * @param pixelBufferData 需要处理的数据。
 * @return 接口调用状态码。
 */
- (kQueenResultCode)processPixelBuffer:(QEPixelBufferData *)pixelBufferData;

/**
 * 处理Texture类型数据。
 * @param textureData 需要处理的数据。
 * @return 接口调用状态码。
 */
- (kQueenResultCode)processTexture:(QETextureData *)textureData;

/**
 * 分析视频帧数据处理。
 * 注意：如处理Texture类型数据时需高级美颜处理需要调用此接口，处理PixelBuffer类型数据不需要调用此接口。
 * @param imageData 帧图片流。
 * @param format 帧图片流颜色格式。
 * @param width 帧图片宽度。
 * @param height 帧图片高度。
 * @param stride 用于检测的图像的跨度(以像素为单位),即每行的字节数, 默认情况下设为 0。
 * @param intputAngle 当前输入帧图片需旋转的角度，计算方式参考Sample工程，注：仅当QueenEngineConfigInfo的autoSettingImgAngle设置为NO才会生效。
 * @param outputAngle 算法输出结果所需旋转的角度，计算方式参考Sample工程，注：仅当QueenEngineConfigInfo的autoSettingImgAngle设置为NO才会生效。
 * @param flipAxis 输出数据的xy轴翻转处理,0为不旋转,1为x轴翻转,2为y轴翻转。
 */
- (void)updateInputDataAndRunAlg:(uint8_t *)imageData withImgFormat:(kQueenImageFormat)format withWidth:(int)width withHeight:(int)height withStride:(int)stride
                  withInputAngle:(int)intputAngle withOutputAngle:(int)outputAngle withFlipAxis:(int)flipAxis;

#pragma mark - "人脸比对"

/**
 * 提取照片中人脸特征
 * @param image: UIImage对象
 * @return 返回特征数组，若无人脸，则内部数据为NA
 */
- (float *)createFaceFeatureWithImage:(UIImage *)image;

/**
 * 提取照片中人脸特征
 * @param rgbBuf: rgb格式的字节数组buf
 * @param width：Buf数据对应画面的宽
 * @param height：Buf数据对应画面的高
 * @return 返回特征数组，若无人脸，则内部数据为NA
 */
- (float *)createFaceFeature:(uint8_t *)rgbBuf withWidth:(int)width withHeight:(int)height;

/**
 * 计算两张人脸的相似度
 * @param faceFeature1：人脸1的特征数据
 * @param faceFeature2：人脸2的特征数据
 * @return：返回打分，分值范围：[0.0-1.0]
 */
- (float)calFaceSimilarityWithFaceFeature1:(float*)faceFeature1 withFaceFeature2:(float *)faceFeature2;

#pragma mark - "调试相关"

/**
 * 展示人脸识别点位。
 * @param show 是否展示。
 */
- (void)showFaceDetectPoint:(BOOL)show;

/**
 * 展示人体识别点位。
 * @param show 是否展示。
 */
- (void)showBodyDetectPoint:(BOOL)show;

/**
 * 展示手部识别点位。
 * @param show 是否展示。
 */
- (void)showHandDetectPoint:(BOOL)show;

/**
 * 展示人脸区域三角剖分线。
 * @param show 是否展示。
 */
- (void)showMakeupLine:(BOOL)show;

/**
 * 展示AR绘制关键点。
 * @param show 是否展示。
 */
- (void)showARWritingDetectPoint:(BOOL)show;

/**
 * 展示物体识别框。
 * @param show 是否展示。
 */
- (void)showObjectDetectPoint:(BOOL)show;

/**
 * 获取运行时上下文信息
 */
- (NSDictionary *)getEngineRuntimeInfo;

@end

#endif
