/**
 * 负责网络请求（仿照Qt版的封装方法，便于快速同步两边的代码）
 *
 * 主要支持的功能：
 *  1，添加公共参数；（注：目前只添加了下划线分割的参数，驼峰版的公共参数请在接口请求中添加，以减少不必要的内存开销）
 *  2，支持 accessToken 的自动刷新逻辑；
 *
 * 使用注意事项：
 *  1，addParam()的key值，setBaseUrl()/setPath() 路径值必须为字符串常量，若动态申请的且在网络未请求完成前释放会导致异常，这样处理目的是节省堆内存开销；
 */

#ifndef XYSDK_HTTP_REQUEST_H
#define XYSDK_HTTP_REQUEST_H



// 在业务层出错的类型
typedef enum {
    xy_res_type_CodeNoError = 0,        // 无错误
    xy_res_type_CodeParamIllegal = 300, // 在调用load()前，参数配置缺失或不合法
    xy_res_type_CodeServerError = 400,  // 服务器返回异常，或资源不存在
    xy_res_type_CodeDataEmpty = 401,   // 服务器返回数据为空
    xy_res_type_CodeDataError = 402,   // 程序错误或数据解析异常
    xy_res_type_CodeNetworkError = 500,  // 网络不可用或请求超时
    xy_res_type_CodeNetworkDisable = 501,  // 设备处于离线状态，请重新检查网络

    // 自定义错误
    xy_res_type_CodeAlbumOutOfStock = 601,  // 专辑已下架
    xy_res_type_CodeAudioRecordFailure = 602,  // 音频录制失败
} xy_res_type_ErrorCode;

// 网络请求方式 GET/POST
typedef enum {
    XY_HTTP_REQUEST_METHOD_GET = 0,
    XY_HTTP_REQUEST_METHOD_POST
} xy_http_request_method;

typedef void(*XYHttpFunctionSuccess)(void* context, const char *body);
typedef void(*XYHttpFunctionFailure)(void* context, const xy_res_type_ErrorCode errorCode);


// 结果拦截器，临时用于扩展成功或失败的参数（避免大量改动原有定义），如果返回true将不会再回调成功和失败
typedef bool(*XYHttpFunctionResponseIntercept)(void* context, const char *body, const int httpCode);

// 网络请求的参数
typedef struct XYHttpParamKeyValue {
    const char *key;        // key值需要时字符串常量，只会保存指针
    char *value;
    bool copyValue;   // 如果值=true，将只保存指针而非拷贝来节省内存分配开销，默认为false
    struct XYHttpParamKeyValue *next;
} XYHttpParamKeyValue;


// 网络请求的路径参数和回调
typedef struct {
    const char *baseUrl;  // 为空时使用默认 XIMALAYA_BASE_URL 宏定义的URL   （要求值为字符串常量，以节省内存开销）
    const char *path;     // URL路径，如：ximalaya-api/xxx/xxx      （要求值为字符串常量，以节省内存开销）
    xy_http_request_method method;
    XYHttpParamKeyValue *paramHead;
    bool requireCamelCaseCommonParams;
    uint32_t bindPageIncreamentId;      // 绑定的页面自增长ID，若值大于零时，会判断当前栈顶的页面ID是否等于该值，不等于时会取消网络请求和回调

    XYHttpFunctionSuccess successCallback;
    XYHttpFunctionFailure failureCallback;
    XYHttpFunctionResponseIntercept responseIntercept;
    void *callbackContext;

    char *jsonBody;
    XYHttpResponseData *response_buff;

    // 私有成员（外部不应该访问）
    void *_tokenIntercept;
} xy_http_request_model;

// Token的类型，以此自动刷新Token
typedef enum {
    xy_http_request_TokenNone = 0,  // 不需要Token
    xy_http_request_TokenAccess = 1,   // 开放平台关联用户的AccessToken
    xy_http_request_TokenNotNull = 2,   // 当无有效token时，使用临时token
} xy_http_request_TokenType;

// 网络请求的优先级
typedef enum {
    xy_http_request_PriorityCritical = -100,       // 最高优先级
    xy_http_request_PriorityHigh = -50,
    xy_http_request_PriorityMedium = 0,
    xy_http_request_PriorityLow = 50,
    xy_http_request_PriorityTrivial = 100,
} xy_http_request_Priority;

xy_http_request_model* xy_http_request_create(XYHttpFunctionSuccess successCallback, XYHttpFunctionFailure failureCallback, void* callbackContext);

// 网络请求基础功能
void xy_http_request_setBaseUrl(xy_http_request_model *model, const char *baseUrl);
void xy_http_request_setPath(xy_http_request_model *model, const char *path);
void xy_http_request_setMethod(xy_http_request_model *model, const xy_http_request_method method);
void xy_http_request_addParam(xy_http_request_model *model, const char *key, const char *value);
int xy_http_request_request(xy_http_request_model *model);
void xy_http_request_requestDelay(xy_http_request_model *model, const int delayMS);
void xy_http_request_requestDelayPriority(xy_http_request_model *model, const int delayMS, const xy_http_request_Priority priority);

// 扩展功能
void xy_http_request_bindPageIncreamentId(xy_http_request_model *model, const uint32_t increamentId);
void xy_http_request_setResponseIntercept(xy_http_request_model *model, XYHttpFunctionResponseIntercept responseIntercept);

// 设置接口是否带驼峰命名的参数（默认为false，以节省内存空间）
void xy_http_request_requireCamelCaseCommonParams(xy_http_request_model *model, const bool require);

// 请求体为JSON（内部在上传成功后，自动释放 json，所以外部释放会导致闪退）
void xy_http_request_setJsonBody(xy_http_request_model *model, char *json);


// 拦截器扩展（token自动刷新功能）
typedef void(*xy_http_intercept_emitHttpFailure)(const char* errorMsg, xy_http_request_model *model, char* response);

void xy_http_request_addTokenParam(xy_http_request_model *model, const char *key, const xy_http_request_TokenType tokenType);

// URL编码，如果检查到字符串中没有要编码的值返回NULL，以节省内存
char* xy_http_request_encodeURL(const char* sourceURL);

// 移除某个参数，如果未找到返回false
bool xy_http_request_removeParam(xy_http_request_model *model, const char *key);

void xy_http_request_destroy(xy_http_request_model *model);

#endif // XYSDK_HTTP_REQUEST_H