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

#include "BaseConfig.h"
#include "JZsdkLib.h"

#include "./RK_Rga.h"
#include "MediaProc/RgaProc/RgaParam.h"

#ifdef RTK_RGA_STATUS_ON

float get_bpp_from_format(int format) 
{
    float bpp = 0;

    switch (format) 
    {
        case RK_FORMAT_RGBA2BPP:
            return 0.25;
        case RK_FORMAT_Y4:
            bpp = 0.5;
            break;
        case RK_FORMAT_BPP1:
        case RK_FORMAT_BPP2:
        case RK_FORMAT_BPP4:
        case RK_FORMAT_BPP8:
        case RK_FORMAT_YCbCr_400:
            bpp = 1;
            break;
        case RK_FORMAT_YCbCr_420_SP:
        case RK_FORMAT_YCbCr_420_P:
        case RK_FORMAT_YCrCb_420_P:
        case RK_FORMAT_YCrCb_420_SP:
            bpp = 1.5;
            break;
        case RK_FORMAT_RGB_565:
        case RK_FORMAT_RGBA_5551:
        case RK_FORMAT_RGBA_4444:
        case RK_FORMAT_BGR_565:
        case RK_FORMAT_BGRA_5551:
        case RK_FORMAT_BGRA_4444:
        case RK_FORMAT_ARGB_5551:
        case RK_FORMAT_ARGB_4444:
        case RK_FORMAT_ABGR_5551:
        case RK_FORMAT_ABGR_4444:
        case RK_FORMAT_YCbCr_422_SP:
        case RK_FORMAT_YCbCr_422_P:
        case RK_FORMAT_YCrCb_422_SP:
        case RK_FORMAT_YCrCb_422_P:
        /* yuyv */
        case RK_FORMAT_YVYU_422:
        case RK_FORMAT_VYUY_422:
        case RK_FORMAT_YUYV_422:
        case RK_FORMAT_UYVY_422:
        case RK_FORMAT_YVYU_420:
        case RK_FORMAT_VYUY_420:
        case RK_FORMAT_YUYV_420:
        case RK_FORMAT_UYVY_420:
            bpp = 2;
            break;
        /*RK encoder requires alignment of odd multiples of 256.*/
        /*Here bpp=2 guarantee to read complete data.*/
        case RK_FORMAT_YCbCr_420_SP_10B:
        case RK_FORMAT_YCrCb_420_SP_10B:
            bpp = 2;
            break;
        case RK_FORMAT_YCbCr_422_10b_SP:
        case RK_FORMAT_YCrCb_422_10b_SP:
            bpp = 2.5;
            break;
        case RK_FORMAT_BGR_888:
        case RK_FORMAT_RGB_888:
            bpp = 3;
            break;
        case RK_FORMAT_RGBA_8888:
        case RK_FORMAT_RGBX_8888:
        case RK_FORMAT_BGRA_8888:
        case RK_FORMAT_BGRX_8888:
        case RK_FORMAT_ARGB_8888:
        case RK_FORMAT_XRGB_8888:
        case RK_FORMAT_ABGR_8888:
        case RK_FORMAT_XBGR_8888:
            bpp = 4;
            break;
        default:
            printf("Is unsupport format now, please fix \n");
            return 0;
    }

    return bpp;
}

T_JZsdkReturnCode RK_Rga_ImageInit(struct RK_RgaImage **RgaImage, int width, int height, int format, 
                                    int Rect_x, int Rect_y, int Rect_w, int Rect_h)
{
    if ((*RgaImage) != NULL)
    {
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
    }

    (*RgaImage) = (struct RK_RgaImage *)malloc(sizeof(struct RK_RgaImage));
    if ((*RgaImage) == NULL)
    {
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }
    
    (*RgaImage)->width = width;
    (*RgaImage)->height = height;
    (*RgaImage)->format = format;


    (*RgaImage)->buf_size = width * height * get_bpp_from_format(format);
    (*RgaImage)->buf = (unsigned char *)malloc((*RgaImage)->buf_size * sizeof(unsigned char));
    if ((*RgaImage)->buf == NULL)
    {
        return JZ_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
    }
    
    (*RgaImage)->handle_param.width = width;
    (*RgaImage)->handle_param.height = height;
    (*RgaImage)->handle_param.format = format;

    (*RgaImage)->handle = importbuffer_virtualaddr((*RgaImage)->buf,  &(*RgaImage)->handle_param);
    if ((*RgaImage)->handle == 0)
    {
        printf("importbuffer_virtualaddr failed\n");
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;
    }

    memset(&(*RgaImage)->img, 0, sizeof((*RgaImage)->img));
    (*RgaImage)->img  = wrapbuffer_handle((*RgaImage)->handle, (*RgaImage)->width, (*RgaImage)->height, (*RgaImage)->format);

    (*RgaImage)->rect.x = Rect_x;
    (*RgaImage)->rect.y = Rect_y;
    (*RgaImage)->rect.width = Rect_w;
    (*RgaImage)->rect.height = Rect_h;

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

T_JZsdkReturnCode RK_Rga_ImageDeInit(struct RK_RgaImage **RgaImage)
{
    if ((*RgaImage)->handle != 0)
    {
        releasebuffer_handle((*RgaImage)->handle);
        (*RgaImage)->handle = 0;
    }
    
    if ((*RgaImage)->buf != NULL)
    {
        free((*RgaImage)->buf);
        (*RgaImage)->buf = NULL;
    }

    if((*RgaImage) != NULL)
    {
        free((*RgaImage));
        (*RgaImage) = NULL;
    }
    
    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

#endif