/*
 * Copyright (C) 2019-2020 Intel Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "PGUtils"

#include <stdint.h>

#include <vector>

#include "iutils/Utils.h"
#include "iutils/CameraLog.h"

#include "PGUtils.h"

namespace icamera {

namespace PGUtils {

/* ************************************************************
 * Common definitions
 * ***********************************************************/

#define GET_FOURCC_FMT(a, b, c, d) ((uint32_t)(d) | ((uint32_t)(c) << 8) \
                                 | ((uint32_t)(b) << 16) | ((uint32_t)(a) << 24))

struct FormatMap {
    int v4l2Fmt;
    ia_css_frame_format_type cssFmt;

    int cssBpp;
};

static const FormatMap sFormatMapping[] = {
    { V4L2_PIX_FMT_YUYV,   IA_CSS_DATA_FORMAT_YUYV, 12 },
    { V4L2_PIX_FMT_UYVY,   IA_CSS_DATA_FORMAT_UYVY, 12 },
    { V4L2_PIX_FMT_YUV420, IA_CSS_DATA_FORMAT_YUV420, 16 },
    { V4L2_PIX_FMT_NV12,   IA_CSS_DATA_FORMAT_NV12, 8 },
    { V4L2_PIX_FMT_NV16,   IA_CSS_DATA_FORMAT_NV16, 12 },
    { V4L2_PIX_FMT_RGB565, IA_CSS_DATA_FORMAT_RGB565, 16 },
    { V4L2_PIX_FMT_RGB24,  IA_CSS_DATA_FORMAT_RGB888, 24 },
    { V4L2_PIX_FMT_RGB32,  IA_CSS_DATA_FORMAT_RGBA888, 24 },
    { V4L2_PIX_FMT_SGRBG12, IA_CSS_DATA_FORMAT_RAW, 16 },
    { V4L2_PIX_FMT_SGRBG10, IA_CSS_DATA_FORMAT_RAW, 16 }, // IA_CSS_DATA_FORMAT_BAYER_GRBG or IA_CSS_DATA_FORMAT_RAW ?

    { GET_FOURCC_FMT('Y', 'U', 'Y', 'V'), IA_CSS_DATA_FORMAT_YUYV, 12 },
    { GET_FOURCC_FMT('U', 'Y', 'V', 'Y'), IA_CSS_DATA_FORMAT_UYVY, 12 },
    { GET_FOURCC_FMT('Y', 'U', '1', '2'), IA_CSS_DATA_FORMAT_YUV420, 16 },
    { GET_FOURCC_FMT('N', 'V', '1', '2'), IA_CSS_DATA_FORMAT_NV12, 8 },
    { GET_FOURCC_FMT('N', 'V', '1', '6'), IA_CSS_DATA_FORMAT_NV16, 12 },
    { GET_FOURCC_FMT('R', 'G', 'B', 'P'), IA_CSS_DATA_FORMAT_RGB565, 16 },
    { GET_FOURCC_FMT('R', 'G', 'B', '3'), IA_CSS_DATA_FORMAT_RGB888, 24 },
    { GET_FOURCC_FMT('R', 'G', 'B', '4'), IA_CSS_DATA_FORMAT_RGBA888, 24 },
    { GET_FOURCC_FMT('B', 'A', '1', '2'), IA_CSS_DATA_FORMAT_RAW, 16 },
    { GET_FOURCC_FMT('B', 'A', '1', '0'), IA_CSS_DATA_FORMAT_RAW, 16 }, // IA_CSS_DATA_FORMAT_BAYER_GRBG or IA_CSS_DATA_FORMAT_RAW ?
    { GET_FOURCC_FMT('y', '0', '3', '2'), IA_CSS_DATA_FORMAT_YYUVYY_VECTORIZED, 16 },
    { GET_FOURCC_FMT('V', '4', '2', '0'), IA_CSS_DATA_FORMAT_YUV420, 16 },
    { GET_FOURCC_FMT('b','V','0','K'),    IA_CSS_DATA_FORMAT_BAYER_VECTORIZED, 16 },
    { GET_FOURCC_FMT('C','S','L','6'),    IA_CSS_DATA_FORMAT_BAYER_LINE_INTERLEAVED, 16},
    { GET_FOURCC_FMT('G','R','1','0'),    IA_CSS_DATA_FORMAT_BAYER_GRBG, 16 },
    { GET_FOURCC_FMT('I','Y','U','V'),    IA_CSS_DATA_FORMAT_YUV420, 12 },
};

static int getStride(int cssFmt, int width);

ia_css_frame_format_type getCssFmt(int v4l2Fmt) {
    int size = ARRAY_SIZE(sFormatMapping);
    for (int i = 0; i < size; i++) {
        if (sFormatMapping[i].v4l2Fmt == v4l2Fmt) {
            return sFormatMapping[i].cssFmt;
        }
    }

    LOG2("%s: unsupported v4l2 pixel format: %s", __func__,
         CameraUtils::format2string(v4l2Fmt).c_str());
    return IA_CSS_N_FRAME_FORMAT_TYPES;
}

int getCssStride(int v4l2Fmt, int width) {
    int stride = width;
    ia_css_frame_format_type cssFmt = getCssFmt(v4l2Fmt);
    switch (v4l2Fmt) {
        case GET_FOURCC_FMT('I','Y','U','V'):
            stride = width;
            break;
        default:
            stride = getStride(cssFmt, width);
            break;
    }
    return stride;
}

int getCssBpp(int v4l2Fmt) {
    int size = ARRAY_SIZE(sFormatMapping);
    for (int i = 0; i < size; i++) {
        if (sFormatMapping[i].v4l2Fmt == v4l2Fmt) {
            return sFormatMapping[i].cssBpp;
        }
    }

    LOG2("%s: unsupported v4l2 pixel format: 0x%x", __func__, v4l2Fmt);
    return 8;
}

int getStride(int cssFmt, int width) {
    int stride = width;
    switch (cssFmt) {
        case IA_CSS_DATA_FORMAT_BAYER_GRBG: // GR10
        case IA_CSS_DATA_FORMAT_RAW:        // BA10
            stride = ALIGN_64(width * 2);
            break;
        case IA_CSS_DATA_FORMAT_YYUVYY_VECTORIZED: // y032
            stride = width * 6;
            break;
        case IA_CSS_DATA_FORMAT_BAYER_VECTORIZED: // bv0k
        case IA_CSS_DATA_FORMAT_BAYER_LINE_INTERLEAVED: // css_fourcc_grbg_12_li
            stride = width * 4;
            stride = ALIGN_64(stride);
            break;
        case IA_CSS_DATA_FORMAT_YUV420:
            stride = width * 2;
            stride = ALIGN_64(stride);
            break;
        case IA_CSS_DATA_FORMAT_NV12:
            stride = width;
            break;
        default:
            LOG2("TODO for format: %d", cssFmt);
            break;
    }
    return stride;
}

/* ************************************************************
 * Difference between PGs
 * ***********************************************************/
#define PG_PSYS_IPU6_ISA_LB 187
#define PG_PSYS_IPU6_BB 189
#define PG_PSYS_IPU6_ISL 198

// the below terminals belong to PG_PSYS_IPU6_BB
#define PG_BB_TERMINAL_ID_TNR_REF_IN 4       // data_terminal
#define PG_BB_TERMINAL_ID_TNR_REF_OUT 6      // data_terminal
#define PG_BB_TERMINAL_ID_TNR_SIM_REF_IN 5   // spetial_terminal
#define PG_BB_TERMINAL_ID_TNR_SIM_REF_OUT 7  // spetial_terminal

// the below terminals belong to PG_PSYS_IPU6_ISA_LB
#ifdef IPU_SYSVER_ipu6v5
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L0 20 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L1 21 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L2 22 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L0 23 // param_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L1 24 // param_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L2 25 // param_terminal
#else
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L0 21 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L1 22 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_IN_L2 23 // program_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L0 24 // param_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L1 25 // param_terminal
#define ISA_LB_TERMINAL_ID_DVS_FE_OUT_L2 26 // param_terminal
#endif

bool getTerminalPairs(int pgId, TERMINAL_PAIR_TYPE type, std::vector<TerminalPair>* pairs) {
    LOG2("@%s, pgId:%d, type:%d, pairs:%p", __func__, pgId, type, pairs);
    CheckError(!pairs, false, "@%s, pairs is nullptr", __func__);

    struct TerminalPairs {
        int pgId;
        TERMINAL_PAIR_TYPE type;
        std::vector<TerminalPair> pairs;
    };
    static const TerminalPairs tps[] = {
        {PG_PSYS_IPU6_BB, TERMINAL_PAIR_TNR,
            {{PG_BB_TERMINAL_ID_TNR_REF_IN, PG_BB_TERMINAL_ID_TNR_REF_OUT}}},
        {PG_PSYS_IPU6_BB, TERMINAL_PAIR_TNR_SIM,
            {{PG_BB_TERMINAL_ID_TNR_SIM_REF_IN, PG_BB_TERMINAL_ID_TNR_SIM_REF_OUT}}},
        {PG_PSYS_IPU6_ISA_LB, TERMINAL_PAIR_DVS,
            {{ISA_LB_TERMINAL_ID_DVS_FE_IN_L0, ISA_LB_TERMINAL_ID_DVS_FE_OUT_L0},
             {ISA_LB_TERMINAL_ID_DVS_FE_IN_L1, ISA_LB_TERMINAL_ID_DVS_FE_OUT_L1},
             {ISA_LB_TERMINAL_ID_DVS_FE_IN_L2, ISA_LB_TERMINAL_ID_DVS_FE_OUT_L2}}}
    };

    for (unsigned int i = 0; i < ARRAY_SIZE(tps); i++) {
        if (tps[i].pgId == pgId && tps[i].type == type) {
            *pairs = tps[i].pairs;
            return true;
        }
    }

    return false;
}

} // name space PGUtils
} // namespace icamera
