#include "isp_aiq.h"

#include <uAPI2/rk_aiq_user_api2_sysctl.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct isp_aiq {
    rk_aiq_sys_ctx_t *ctx;
    int camera_id;
};

isp_aiq_t *isp_aiq_start(const isp_aiq_cfg_t *cfg) {
    if (!cfg || !cfg->iq_dir || !cfg->iq_dir[0] || cfg->camera_id < 0) {
        fprintf(stderr, "[isp] invalid AIQ configuration\n");
        return NULL;
    }

    rk_aiq_static_info_t info;
    memset(&info, 0, sizeof(info));
    XCamReturn ret = rk_aiq_uapi2_sysctl_enumStaticMetasByPhyId(cfg->camera_id, &info);
    if (ret != XCAM_RETURN_NO_ERROR) {
        fprintf(stderr, "[isp] cannot enumerate camera %d: %d\n", cfg->camera_id, ret);
        return NULL;
    }

    if (!info.sensor_info.sensor_name[0]) {
        fprintf(stderr, "[isp] camera %d has no sensor entity\n", cfg->camera_id);
        return NULL;
    }

    if (setenv("HDR_MODE", "0", 1) != 0) {
        fprintf(stderr, "[isp] cannot set HDR_MODE\n");
        return NULL;
    }

    ret = rk_aiq_uapi2_sysctl_preInit_devBufCnt(
        info.sensor_info.sensor_name, "rkraw_rx", 2);
    if (ret != XCAM_RETURN_NO_ERROR) {
        fprintf(stderr, "[isp] warning: preInit_devBufCnt failed: %d\n", ret);
    }

    rk_aiq_sys_ctx_t *ctx = rk_aiq_uapi2_sysctl_init(
        info.sensor_info.sensor_name, cfg->iq_dir, NULL, NULL);
    if (!ctx) {
        fprintf(stderr,
                "[isp] AIQ init failed: camera=%d sensor=%s iq-dir=%s\n",
                cfg->camera_id, info.sensor_info.sensor_name, cfg->iq_dir);
        return NULL;
    }

    ret = rk_aiq_uapi2_sysctl_prepare(ctx, 0, 0, RK_AIQ_WORKING_MODE_NORMAL);
    if (ret != XCAM_RETURN_NO_ERROR) {
        fprintf(stderr, "[isp] AIQ prepare failed: %d\n", ret);
        rk_aiq_uapi2_sysctl_deinit(ctx);
        return NULL;
    }

    ret = rk_aiq_uapi2_sysctl_start(ctx);
    if (ret != XCAM_RETURN_NO_ERROR) {
        fprintf(stderr, "[isp] AIQ start failed: %d\n", ret);
        rk_aiq_uapi2_sysctl_deinit(ctx);
        return NULL;
    }

    isp_aiq_t *isp = (isp_aiq_t *)calloc(1, sizeof(*isp));
    if (!isp) {
        fprintf(stderr, "[isp] out of memory\n");
        rk_aiq_uapi2_sysctl_stop(ctx, false);
        rk_aiq_uapi2_sysctl_deinit(ctx);
        return NULL;
    }

    isp->ctx = ctx;
    isp->camera_id = cfg->camera_id;
    fprintf(stderr, "[isp] AIQ started: camera=%d sensor=%s iq-dir=%s\n",
            cfg->camera_id, info.sensor_info.sensor_name, cfg->iq_dir);
    return isp;
}

void isp_aiq_stop(isp_aiq_t *isp) {
    if (!isp) return;
    if (isp->ctx) {
        fprintf(stderr, "[isp] stopping AIQ camera=%d\n", isp->camera_id);
        rk_aiq_uapi2_sysctl_stop(isp->ctx, false);
        rk_aiq_uapi2_sysctl_deinit(isp->ctx);
        isp->ctx = NULL;
    }
    free(isp);
}
