//
// Created by karl on 20-12-23, being enriched and maintained by swh.
//

#pragma once

#ifndef PLUGINSR_H
#define PLUGINSR_H
#include <string>
#define VIDEO_DATA_ARRAY_COUNT    ( 4 )

typedef void* TextureObjectRef;

/**
 错误码
 */
enum PluginErrorCode{
    PluginErrorCodeFailed = -1,           /* 失败 */
    PluginErrorCodeSuccess = 0,           /* 成功 */

    PluginErrorCodeMallocFailed = -300,   /* 内存申请失败 */

    PluginErrorCodeVertShaderCompileFailed = -400,   /* vert shader 编译失败 */
    PluginErrorCodeFragShaderCompileFailed = -401,   /* frag shader 编译失败 */
    PluginErrorCodeShaderLinkFailed = -402,          /* shader 链接 program 失败 */

    PluginErrorCodeFBOStatusAbnormal = -500,         /* 初始化FBO，FBO状态异常; 如果是-50000，表明状态异常发生在算法运行 */

    PluginErrorCodeFailedD1 = -101,       /* 降级网络初始化失败类型1 */
    PluginErrorCodeFailedD2 = -102,       /* 降级网络初始化失败类型2 */
    PluginErrorCodeFailedD3 = -103,       /* 降级网络初始化失败类型3 */
    PluginErrorCodeFailedD4 = -104,       /* 降级网络初始化失败类型4 */
    PluginErrorCodeFailedM1 = -201,       /* 主网络初始化失败类型1 */
    PluginErrorCodeFailedM2 = -202,       /* 主网络初始化失败类型2 */
    PluginErrorCodeFailedM3 = -203,       /* 主网络初始化失败类型3 */
    PluginErrorCodeFailedM4 = -204,       /* 主网络初始化失败类型4 */
};


/**
 数据处理返回码
*/
enum PluginProcessCode{
    PluginProcessCodeFailed = -1,                   /* 数据处理失败 */
    PluginProcessCodeSuccess = 0,                   /* 数据处理成功 (使用主网络) */
    PluginProcessCodeSuccessLite = 3,               /* 数据处理成功 (使用降级网络) */
    PluginProcessCodeFrame1 = 1,                    /* 算法成功输出第一帧 */
    PluginProcessCodeFrame2 = 2,                    /* 算法成功输出第二帧 */
    PluginProcessCodeInitFailed = -2,               /* 算法初始化失败，无法执行算法 */
    PluginProcessCodeDeviceError = -3,              /* 无合适设备执行算法 */
    PluginProcessCodeNetInvokeFailed = -4,          /* 网络调用失败，算法无法执行 */
    PluginProcessCodeOversize = 11,                 /* 输入视频宽高超出预定范围，算法不启动 */
    PluginProcessCodeResizeFailed = 21,             /* 网络输入宽高调整（所谓"resize"）失败，算法无法进行 */
    PluginProcessCodeDoingResize = 22,              /* 网络输入宽高调整（所谓"resize"）进行中，完成前算法无法进行 */
    PluginProcessCodeFBOStatusAbnormal = 31,        /* FBO 状态异常，算法无法进行 */
    PluginProcessCodeLackOfPerformanceExit = 41,    /* 当前计算单元处理当前输入宽高的帧计算速度慢，不适合运行算法，算法退出 */

    PluginProcessCodeNonPBAFFrame = 51,             /* 非正常帧：IOS下，输入非PBAFFrame帧 */
};

/**
 视频数据支持类型
 */
enum PluginVideoType{
    PluginVideoTypeI420,
    PluginVideoTypeNV12,
    PluginVideoTypeNV21,
    PluginVideoTypeRGB,
    PluginVideoTypeRGBA,
};

/**
 视频数据格式，结构体字节对齐
 */
typedef struct _tagVideoData {
    uint32_t    width;              //图像宽
    uint32_t    height;             //图像高
    uint8_t*    data;               //图像数据
    PluginVideoType    data_type;   //图像格式
    uint8_t*    data_ptr[VIDEO_DATA_ARRAY_COUNT];   //图像各通道头指针
    uint32_t    stride[VIDEO_DATA_ARRAY_COUNT];     //图像各通道stride
}VideoData;

enum TextureType {
    GLES_Texture2D = 0,
    GLES_Texture2D_OES = 1
};

enum NetType {
    NetMain = 2,
    NetDegrade = 1,
    NetDefault = 0,
};

struct TextureInput {
    // 输入Texture内容宽高
    int in_width;
    int in_height;
    int in_texture;
    TextureType in_texture_type;

    // This array must be either `null` or exactly 16 elements.(4x4 column major matrix)
    float* in_transform_matrix = nullptr;

    // 需要写入超分数据的Texture，设置0时SDK将超分内容写入内部Texture并把该Texture写入本字段
    uint32_t out_texture = 0;
    // 如果`out_texture`为0时（即使用SDK申请的texture作为输出），用以下两个字段告知用户内部Texture对应真实宽高
    int out_texture_width = 0;
    int out_texture_height = 0;

    //  如果`out_texture`为0时（即使用SDK申请的texture作为输出），本ref作为texture的引用句柄，需要在使用完毕后调用`release_internal_texture`完成释放
    TextureObjectRef out_texture_ref = nullptr;

    // Debug options
    bool watermark_enabled = false;

#ifdef __ANDROID__
    int frameStatus = 0;

    double TimeTexRead;
    double TimeSRFunc;
    double TimeTexWrite;
#endif
};

class SuperResolutionInterface {

public:
    virtual ~SuperResolutionInterface() {};

    /*
     create superresolution algorithm instance
     */
    static SuperResolutionInterface* Create();

    /*
     get algorithm support data format
     */
    virtual uint32_t GetSupportFormat() = 0;

    /*
     Select Net,
     Default is that net is selected by lib itself.
     NetMain, always use main net, however use degraded net once main net is lack of performance.
     NetDegrade, always use degraded net.
     */
    virtual int32_t SelectNetType(NetType Type) = 0;

    /*
     init memory or other resource
     */
    virtual int32_t Init(std::string cacheDir) = 0;

    /*
     clear all memory or other resource
     和 Init成对调用
     */
    virtual int32_t Clear() = 0;

    /*
     process data
     */
#ifdef __APPLE__
    virtual int32_t ProcessData(VideoData* input_data, VideoData* out_data) = 0;
#endif
#ifdef __ANDROID__
    virtual int32_t ProcessDataTex(TextureInput* input) = 0;
#endif
    
    virtual int32_t SetFrameStatus() = 0;

    /*
     * 获取设备类型
     */
    virtual int32_t GetDeviceType() = 0;
};


#endif //PLUGINSR_H
