////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2019-2023 Qualcomm Technologies, Inc.
// All Rights Reserved.
// Confidential and Proprietary - Qualcomm Technologies, Inc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __IS_INTERFACE_UTILS_H__
#define __IS_INTERFACE_UTILS_H__

/*------------------------------------------------------------------------
*       Include Files
* ----------------------------------------------------------------------- */

#include "is_interface.h"
#include "ipe_data.h"

#ifdef __cplusplus
extern "C" {
#endif

/*------------------------------------------------------------------------
*       Definitions and Macros
* ----------------------------------------------------------------------- */

#define EIS_UTIL_MAX_FILE_PREFIX_LENGTH     128  /**< Maximal length of file prefix, including terminating null char */

/*------------------------------------------------------------------------
*       Data structures
* ----------------------------------------------------------------------- */
typedef enum is_utils_log_outputs_e
{
    IS_UTILS_FLAG_NONE          = 0x00000000,   /**< No data will be written.
                                                 *   @warning if eis_utils_log_init() is called with this flag it will return with error.
                                                 */
    IS_UTILS_FLAG_WRITE_INPUT   = 0x00000001,   /**< Write input data of EIS algorithm to file */
    IS_UTILS_FLAG_WRITE_OUTPUT  = 0x00000002,   /**< Write output data of EIS algorithm to file */
    IS_UTILS_FLAG_LOGCAT_INPUT  = 0x00000004,   /**< Write output data of EIS algorithm to logcat */
    IS_UTILS_FLAG_LOGCAT_OUTPUT = 0x00000008,   /**< Write output data of EIS algorithm to logcat */

    IS_UTILS_FLAG_DEFAULT       = IS_UTILS_FLAG_WRITE_INPUT,   /**< Default flags */

    IS_UTILS_FLAG_ALL           = IS_UTILS_FLAG_WRITE_INPUT |
                                  IS_UTILS_FLAG_WRITE_OUTPUT |
                                  IS_UTILS_FLAG_LOGCAT_INPUT |
                                  IS_UTILS_FLAG_LOGCAT_OUTPUT,
}is_utils_log_flags;

/** log utility initial common configurations data structure */
typedef struct is_utils_log_init_s
{
    is_init_data_common*    init_common;                                    /**< Common configuration, as passed to eis3_initialize() or eis2_initialize() */
    is_init_data_sensor*    init_sensors;                                   /**< Per sensor configuration, as passed to eis3_initialize() or eis2_initialize() */
    uint32_t                num_sensors;                                    /**< init_sensors array size */
    is_utils_log_flags      flags;                                          /**< Defines the logging system flags */

    bool                    enable_output_stabilize_to_single_grid;         /**< enable bit for saving eis_utility_convert_output_stabilize_to_single_grid() output to file. if IS_UTILS_FLAG_WRITE_OUTPUT is not defined then this value is ignored */
    bool                    enable_calc_alignment_matrix;                   /**< enable bit for saving eis_utility_calc_alignment_matrix() output to file. if IS_UTILS_FLAG_WRITE_OUTPUT is not defined then this value is ignored */
    bool                    enable_ud_alignment_matrix_to_distorted_grid;   /**< enable bit for saving eis_utility_convert_ud_alignment_matrix_to_distorted_grid() output to file. if IS_UTILS_FLAG_WRITE_OUTPUT is not defined then this value is ignored */
    bool                    enable_get_shifted_roi;                         /**< enable bit for saving eis_utility_get_shifted_roi() output to file. if IS_UTILS_FLAG_WRITE_OUTPUT is not defined then this value is ignored */
//    bool                    enable_get_eis_approx_crop;                     /**< enable bit for saving eis_utility_get_eis_approx_crop() output to file. if IS_UTILS_FLAG_WRITE_OUTPUT is not defined then this value is ignored */

    char                    file_prefix[EIS_UTIL_MAX_FILE_PREFIX_LENGTH];   /**< file prefix, as it will be written to file system */
}is_utils_log_init;

typedef struct is_utils_log_aux_output_s
{
    uint32_t            frame_id;                                   /**< frame id */
    uint32_t            active_sensor_id;                           /**< active sensor index */

    NcLibWarpGrid*      output_stabilize_to_single_grid;            /**< Output of eis_utility_convert_output_stabilize_to_single_grid() */
    NcLibWarpMatrices*  calc_alignment_matrix;                      /**< Output of eis_utility_calc_alignment_matrix() */
    NcLibWarp*          ud_alignment_matrix_to_distorted_grid;      /**< Output of eis_utility_convert_ud_alignment_matrix_to_distorted_grid() */
    WindowRegionF*      get_shifted_roi;                            /**< Output of eis_utility_get_shifted_roi() */
//    WindowRegionF*      get_eis_approx_crop;                        /**< Output of eis_utility_get_eis_approx_crop() */
} is_utils_log_aux_output;

/** log utility common configurations data structure */
typedef struct is_utils_log_write_data_s
{
    is_input_t*                             is_input;                               /**< EIS algorithm input struct for eis3_process() or eis2_process().
                                                                                     *   @warning: In case algorithm was initialized with is_type defined as IS_TYPE_DISTORTION_CORRECTION_ONLY this value will be ignored
                                                                                     */
    is_input_distortion_correction_t*       is_input_distortion_correction;         /**< EIS algorithm input struct for eis3_process_distortion_correction()
                                                                                     *   @warning: In case algorithm was initialized with is_type defined as IS_TYPE_EIS_NFL this value will be ignored
                                                                                     */
    is_input_stabilize_t*                   is_input_stabilize;                     /**< EIS algorithm input struct for eis3_process_stabilize()
                                                                                     *   @warning: In case algorithm was initialized with is_type defined as IS_TYPE_EIS_NFL or IS_TYPE_DISTORTION_CORRECTION_ONLY this value will be ignored
                                                                                     */
    is_input_snapshot_stabilize_t*          is_input_snapshot_stabilization;        /**< EIS algorithm input struct for eis2_process_snapshot() */

    is_time_intervals*                      is_output_time_intervals;               /**< EIS algorithm output struct */

    is_output_t*                            is_output;                              /**< EIS algorithm output struct for eis3_process() or eis2_process() */
    is_output_distortion_correction_t*      is_output_distortion_correction;        /**< EIS algorithm output struct for eis3_process_distortion_correction()
                                                                                     *   @warning: In case algorithm was initialized with is_type defined as IS_TYPE_EIS_NFL this value will be ignored
                                                                                     */
    is_output_stabilize_t*                  is_output_stabilize;                    /**< EIS algorithm output struct for eis3_process_stabilize()
                                                                                     *   @warning: In case algorithm was initialized with is_type defined as IS_TYPE_EIS_NFL or IS_TYPE_DISTORTION_CORRECTION_ONLY this value will be ignored
                                                                                     */
    is_output_snapshot_stabilize_t*         is_output_snapshot_stabilization;       /**< EIS algorithm output struct for eis2_process_snapshot() */

    is_utils_log_aux_output*                aux;                                    /**< Optional value could be NULL. when this is non-NULL all other could be NULL */

    char*                                   buffer;                                 /**< Additional per frame buffer to be saved,
                                                                                     *   string will be appended to end of frame line in frame output file
                                                                                     */
}is_utils_log_write_data;

/*------------------------------------------------------------------------
*       API Declarations
* ----------------------------------------------------------------------- */

/**
*  @brief    Returns the absolute gyro bias as estimated by EIS algorithm
*
*  @param [out]     gyro_bias       Absolute gyro bias as estimated by EIS algorithm, units are in [rad/sec]
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_get_estimated_bias(sample_data_t* gyro_bias);

/**
* @deprecated Use eis_utility_convert_to_window_regions_deployment() instead, will be removed in future version
*
*  @brief   Utility function that coverts window regions in Hana format to Kona (GeoLib)
*
*  @note    Use only in case GeoLib is not present in the system
*
*  @param [in]  ife                         IFE crop window
*  @param [in]  ipe                         IPE digital zoom window
*  @param [in]  stabilization_crop_ratio_x  stabilization crop ratio for x-axis, as taken from
*                                           eis3_get_stabilization_crop_ratio_ex() or eis2_get_stabilization_crop_ratio_ex()
*  @param [in]  stabilization_crop_ratio_y  stabilization crop ratio for y-axis, as taken from
*                                           eis3_get_stabilization_crop_ratio_ex() or eis2_get_stabilization_crop_ratio_ex()
*  @param [in]  stabilization_input_size_x  Actual stabilization input image size == IPE input size at DZ x1
*  @param [in]  stabilization_input_size_y  Actual stabilization input image size == IPE input size at DZ x1
*  @param [out] eis_window_regions          Window regions as taken by EIS algorithm
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_convert_to_window_regions(
    const WindowRegion* ife,
    const WindowRegion* ipe,
    double              stabilization_crop_ratio_x,
    double              stabilization_crop_ratio_y,
    uint32_t            stabilization_input_size_x,
    uint32_t            stabilization_input_size_y,
    eis_roi_windows*    eis_window_regions);

/**
*  @brief   Utility function that coverts window regions in Hana format to Kona (GeoLib)
*
*  @note    Use only in case GeoLib is not present in the system
*
*  @param [in]  ife                         IFE crop window
*  @param [in]  ipe                         IPE digital zoom window
*  @param [in]  stabilization_crop_ratio_x  stabilization crop ratio for x-axis, as taken from
*                                           eis3_get_stabilization_crop_ratio_ex() or eis2_get_stabilization_crop_ratio_ex()
*  @param [in]  stabilization_crop_ratio_y  stabilization crop ratio for y-axis, as taken from
*                                           eis3_get_stabilization_crop_ratio_ex() or eis2_get_stabilization_crop_ratio_ex()
*  @param [in]  stabilization_input_size_x  Actual stabilization input image size == IPE input size at DZ x1
*  @param [in]  stabilization_input_size_y  Actual stabilization input image size == IPE input size at DZ x1
*  @param [in]  deployment_type             EIS Deployment type
*  @param [out] eis_window_regions          Window regions as taken by EIS algorithm
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_convert_to_window_regions_deployment(
    const WindowRegion*         ife,
    const WindowRegion*         ipe,
    double                      stabilization_crop_ratio_x,
    double                      stabilization_crop_ratio_y,
    uint32_t                    stabilization_input_size_x,
    uint32_t                    stabilization_input_size_y,
    cam_is_deployment_type_t    deployment_type,
    eis_roi_windows*            eis_window_regions);

/**
*  @brief   Utility function that coverts a grid to 9 matrices.
*           A temporary patch for using GPU OpenGL matrices warper instead of GPU Grid warper
*
*  @warning Cannot support LDC at all !!!
*
*  @param [in]      inGrid                        Input grid for conversion
*  @param [out]     outMatrices                   Output 9 matrices
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_convert_grid_to_matrices(const NcLibWarpGrid* inGrid, NcLibWarpMatrices* outMatrices);

/**
*  @brief   Utility function that coverts distortion correction grid and stabilization
*           transforms (grid and matrix) to a single grid. Needed when using GPU grid warper
*
*  @note    Depending on the SW flow change the domain of the transforms to virtual domain (grid only changes by scaling) is possible
*
*
*  @param [in,out]  distortion_correction_grid  Distortion correction grid, output of eis3_process_stabilize() or eis2_process()
*  @param [in,out]  stabilization_transform     Stabilization transform, output of eis3_process_stabilize() or eis2_process()
*  @param [in]      output_image_domain         Optional, Output image domain
*  @param [out]     out                         Single NcLib grid
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_convert_output_stabilize_to_single_grid(
    NcLibWarpGrid*          distortion_correction_grid,
    NcLibWarp*              stabilization_transform,
    const NcLibImageSize*   output_image_domain,
    NcLibWarpGrid*          out);

/**
*  @brief    Output the rotation out2in matrix of the device between two different times
*
*  @param [in]   eis3_handle            EIS 3.x handle of the current active sensor, sensor_index_src, which needs to be aligned to other inactive sensor, sensor_index_dst

*  @param [in]   src_sensor_index       Alignment source sensor index
*  @param [in]   src_mof_gyro_time      Middle of frame (MOF) time of source frame
*  @param [in]   src_window_regions     Source frame window regions
*  @param [in]   dst_sensor_index       Alignment source sensor index
*  @param [in]   dst_mof_gyro_time      Middle of frame (MOF) time of source frame
*  @param [in]   dst_window_regions     Source frame window regions

*  @param [out]  alignment_matrix_out2in Output rotation out2in matrix, which rotates from frame with MOF time of mof_gyro_time_src to frame with MOF time of mof_gyro_time_dst
*
*  @warning     If (sensor_index_src != sensor_index_dst) && ((mof_gyro_time_dst - mof_gyro_time_src) < half of frame time)
*               QIS instance might not contain the gyro information and function call will fail
*
*  @note        For MFHDR gyro based alignment (sensor_index_src == sensor_index_dst), always call with the instance that was called second for that frame (short, long)
*
*  @example     To align Wide (sensor_index_dst) to Tele (sensor_index_src):
*               Must call this method with eis3_handle instance that was last called for eis3_process_distortion_correction() for Wide (sensor_index_dst).
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_calc_alignment_matrix(
    void*                   eis3_handle,
    uint32_t                src_sensor_index,
    uint64_t                src_mof_gyro_time,
    const eis_roi_windows*  src_window_regions,
    uint32_t                dst_sensor_index,
    uint64_t                dst_mof_gyro_time,
    const eis_roi_windows*  dst_window_regions,
    NcLibWarpMatrices*      alignment_matrix_out2in);

/**
*  @brief   Utility function that converts alignment matrix in undistorted domain to alignment transform in distorted
*           domain based on distortion correction grids
*
*           alignment_transform_distorted_out2in := (frame_src_ud_grid_out2in * alignment_ud_out2in * frame_dst_ud_grid_out2in^-1)
*
*
*  @param [in, out]     alignment_ud_out2in                     Alignment matrix in undistorted domain from source to destination in out2in mode.
*  @param [in, out]     frame_src_ud_grid_out2in                Source frame distortion correction grid
*  @param [in, out]     frame_dst_ud_grid_out2in                Destination frame distortion correction grid
*  @param [out]         alignment_transform_distorted_out2in    Output transform in distorted domain
*
*  @note NcLibWarpConvertToVirtualDomain() will be applied internally on each of the following inputs:
*           - alignment_ud
*           - frame_src_ud_grid
*           - frame_dst_ud_grid
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_convert_ud_alignment_matrix_to_distorted_grid(
    NcLibWarpMatrices*              alignment_ud_out2in,
    NcLibWarpGrid*                  frame_src_ud_grid_out2in,
    NcLibWarpGrid*                  frame_dst_ud_grid_out2in,
    NcLibWarp*                      alignment_transform_distorted_out2in);

/**
*  @brief   Final_shifted_roi should be same zoom level as in window_regions but be shifted according to grid and matrix
*           Purpose is to use this shifted ROI for snapshot so snapshot FOV would match the preview actual FOV on the moment of the capture
*
*  @param [in,out]   distortion_correction_grid      distortion_correction_grid from EIS algorithm. Will be converted to virtual domain.
*  @param [in,out]   stabilization_transform         stabilization_transform from EIS algorithm. Will be converted to virtual domain.
*  @param [in]       window_regions                  window_regions as was input to EIS algorithm
*  @param [out]      final_shifted_roi               ROI of total zoom shifted according to EIS combined transforms and SAT if exist
*
*  @note NcLibWarpConvertToVirtualDomain() will be applied internally on each of the following inputs:
*           - distortion_correction_grid
*           - stabilization_transform
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_get_shifted_roi(
    NcLibWarpGrid*                  distortion_correction_grid,
    NcLibWarp*                      stabilization_transform,
    const eis_roi_windows*          window_regions,
    WindowRegionF*                  final_shifted_roi);

/**
*  @brief eis_utility_get_eis_approx_crop approximated crop of EIS from input image. this crop is rect but actual crop at input is polygon due to grid and matrix.
*         it is meant for customer feature request
*
*  @param [in,out]   distortion_correction_grid      distortion_correction_grid from EIS algorithm. Will be converted to virtual domain.
*  @param [in,out]   stabilization_transform         stabilization_transform from EIS algorithm. Will be converted to virtual domain.
*  @param [in]       output_crop_fov                 output_crop_fov as was input to EIS algorithm (output_crop_fov == ICA crop for Stabilization done at ICA == total margins (physical+virtual) + any ipe DZ done at the same ICA with stabilization )
*  @param [out]      eis_approx_crop                 approximated crop of EIS from input image. this crop is rect but actual crop at input is polygon due to grid and matrix.
*
*  @note NcLibWarpConvertToVirtualDomain() will be applied internally on each of the following inputs:
*           - distortion_correction_grid
*           - stabilization_transform
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utility_get_eis_approx_crop(
    NcLibWarpGrid*                  distortion_correction_grid,    // distortion_correction Grid transform, synced with frame_id
    NcLibWarp*                      stabilization_transform,       // Stabilization transform, as passed to NcLib.
    const WindowRegionF*            output_crop_fov,
    WindowRegionF*                  eis_approx_crop);

/**
*  @brief   Initializes EIS log utility
*
*  @param [out] context                     EIS log utility context
*  @param [in]  init_data                   EIS algorithm init data
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_init(
    void**                      context,
    const is_utils_log_init*    init_data);

/**
*  @brief   Write frame information to file
*
*  @param [in]  context                     EIS log utility context
*  @param [in]  data                        frame data to be written
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_write(
    void*                           context,
    const is_utils_log_write_data*  data);

/**
*  @brief   Flush data to file from temporary memory buffer
*
*  @param [in]  _context                    EIS log utility context
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_flush(void* _context);

/**
*  @brief   Flush data to file from temporary memory buffers to files, close them and open new files with
*           the new file prefix supplied
*
*  @param [in]  _context                    EIS log utility context
*  @param [in]  file_prefix                 EIS log file prefix
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_open(void* _context, const char file_prefix[EIS_UTIL_MAX_FILE_PREFIX_LENGTH]);

/**
*  @brief   return status is true if eis_utils_log_open() was called and returned successfully, otherwise false
*
*  @param [in]  _context                    EIS log utility context
*  @param [in]  result                      return status
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_is_opened(void* _context, bool* result);

/**
*  @brief   Flush data from temporary memory buffers to files, and closes them
*
*  @param [in]  _context                    EIS log utility context
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_close(void* _context);

/**
*  @brief   Destroys EIS log utility context
*
*  @param [in,out]  context                 EIS log utility context
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_utils_log_destroy(void** context);

/**
*  @brief  Gets EIS algorithm API version
*
*  @param [out]     major                 EIS library major version
*  @param [out]     minor                 EIS library minor version
*  @param [out]     step                  EIS library step version
*
*  @example On CamX node need to perform the following check:
*
*           uint32_t major, minor, step;
*           if (0 != eis_get_lib_version(&major, &minor, &step))
*           {
*               goto Exit; // Function Failed
*           }
*           if ((IS_API_VERSION_MAJOR != major) || (IS_API_VERSION_MINOR != minor) || (IS_API_VERSION_STEP != step))
*           {
*               goto Exit; // Invalid algorithm version
*           }
*
*  @return 0 in case of success, otherwise failed.
**/
EIS_VISIBILITY_PUBLIC
int32_t eis_get_lib_version(uint32_t* major, uint32_t* minor, uint32_t* step);

#ifdef __cplusplus
}
#endif

#endif /* __IS_INTERFACE_UTILS_H__ */
