/**
 * Copyright 2019,2020,2021 Sony Corporation
 */
 
#ifndef LOAD_LIBRARY_UTILITY_H_
#define LOAD_LIBRARY_UTILITY_H_

#include <memory>
#include <vector>

#include "xr_api_defs.h"
XR_DEFINE_HANDLE(SrdXrSessionHandle);

namespace srd {
    namespace xr {
        namespace utility {

            typedef SrdXrResult(*CREATE_SESSION)(const SrdXrSessionCreateInfo*, SrdXrSessionHandle*);
            typedef SrdXrResult(*DESTROY_SESSIOM)(SrdXrSessionHandle*);
            typedef SrdXrResult(*BEGIN_SESSIOM)(SrdXrSessionHandle, const SrdXrSessionBeginInfo*);
            typedef SrdXrResult(*END_SESSIOM)(SrdXrSessionHandle);
            typedef SrdXrResult(*POLL_EVENT)(SrdXrSessionHandle, SrdXrEventDataBuffer*);
            typedef SrdXrResult(*BEGIN_FRAME)(SrdXrSessionHandle);
            typedef SrdXrResult(*END_FRAME)(SrdXrSessionHandle, const SrdXrFrameEndInfo*);
            typedef SrdXrResult(*LOCATE_VIEWS)(SrdXrSessionHandle, const SrdXrViewLocateInfo*, SrdXrView*);

            /* extension API */
            typedef SrdXrResult(*GET_PLATFORM_SPECIFIC_DATA)(SrdXrSessionHandle, SrdXrPlatformSpecificData*);
            typedef SrdXrResult(*GET_PROJECTIOM_MATRIX)(SrdXrSessionHandle, const SrdXrProjectionMatrixInfo*, SrdXrProjectionMatrix*);
            typedef SrdXrResult(*SET_CLIPPING_DISTANCE)(SrdXrSessionHandle, float, float);
            typedef SrdXrResult(*SET_GRAPHICS_API)(SrdXrSessionHandle, SrdXrGraphicsAPI);
            typedef SrdXrResult(*SET_RENDER_DEVICE)(SrdXrSessionHandle, void*);
            typedef SrdXrResult(*GENERATE_TEXTURE_AND_SHADERS)(SrdXrSessionHandle, SrdXrTexture*, SrdXrTexture*, SrdXrTexture*);

            typedef SrdXrResult(*ENUMERATE_DEVICES)(std::vector<SrdXrDeviceInfo>*);
            typedef SrdXrResult(*GET_DEVICE)(unsigned int, SrdXrDeviceInfo*);
            typedef SrdXrResult(*GET_DEVICE_STATE)(SrdXrSessionHandle, SrdXrDeviceState*);

            typedef SrdXrResult(*LOCATE_DISPLAY)(SrdXrSessionHandle, const SrdXrDisplayLocateInfo*, SrdXrDisplay*);

            typedef SrdXrResult(*SET_DEBUG_LOG_CALLBACK)(SrdXrLogCallback);

            typedef SrdXrResult(*GET_CROSSTALK_CORRECTION_SETTINGS)(SrdXrSessionHandle, SrdXrCrosstalkCorrectionSettings*);
            typedef SrdXrResult(*SET_CROSSTALK_CORRECTION_SETTINGS)(SrdXrSessionHandle, const SrdXrCrosstalkCorrectionSettings*);
            typedef SrdXrResult(*GET_CROSSTALK_CORRECTION_SETTINGS_V1_1_0)(SrdXrSessionHandle, SrdXrCrosstalkCorrectionSettings_v1_1_0*);
            typedef SrdXrResult(*SET_CROSSTALK_CORRECTION_SETTINGS_V1_1_0)(SrdXrSessionHandle, const SrdXrCrosstalkCorrectionSettings_v1_1_0*);
            typedef SrdXrResult(*GET_CROSSTALK_CORRECTION_SYSTEM_SETTINGS)(SrdXrSessionHandle, SrdXrCrosstalkCorrectionSystemSettings*);
            typedef SrdXrResult(*SET_CROSSTALK_CORRECTION_SYSTEM_SETTINGS)(SrdXrSessionHandle, const SrdXrCrosstalkCorrectionSystemSettings*);
            typedef SrdXrResult(*SET_COLOR_MANAGEMENT_SETTINGS)(SrdXrSessionHandle, const SrdXrColorManagementSettings*);
            typedef SrdXrResult(*ENABLE_TEMPERATURE_COMPENSATION)(SrdXrSessionHandle, bool);

            typedef SrdXrResult(*SAVE_USER_SETTINGS)(SrdXrSessionHandle);
            typedef SrdXrResult(*GET_CAMERA_SETTINGS)(SrdXrSessionHandle, SrdXrCameraSettings*);
            typedef SrdXrResult(*SET_CAMERA_SETTINGS)(SrdXrSessionHandle, const SrdXrCameraSettings*);
            typedef SrdXrResult(*GET_CAMERA_GAIN)(SrdXrSessionHandle, float*);
            typedef SrdXrResult(*SET_CAMERA_GAIN)(SrdXrSessionHandle, const float);
            typedef SrdXrResult(*SHOW_CAPTURED_IMAGE_WINDOW)(SrdXrSessionHandle, bool);
            typedef SrdXrResult(*GET_PERFORMANCE_MODE)(SrdXrSessionHandle, SrdXrPerformanceMode*);
            typedef SrdXrResult(*SET_PERFORMANCE_MODE)(SrdXrSessionHandle, const SrdXrPerformanceMode);

            typedef SrdXrResult(*PAUSE_HEAD_TRACKING)(SrdXrSessionHandle);
            typedef SrdXrResult(*RESUME_HEAD_TRACKING)(SrdXrSessionHandle);

            /* Debug API */
            typedef SrdXrResult(*GET_FLOAT_WITH_QUERY)(SrdXrSessionHandle, const char*, float*);
            typedef SrdXrResult(*SET_FLOAT_WITH_QUERY)(SrdXrSessionHandle, const char*, float);
            typedef SrdXrResult(*GET_INT_WITH_QUERY)(SrdXrSessionHandle, const char*, int*);
            typedef SrdXrResult(*SET_INT_WITH_QUERY)(SrdXrSessionHandle, const char*, int);
            typedef SrdXrResult(*GET_STRING_WITH_QUERY)(SrdXrSessionHandle, const char*, char**);
            typedef SrdXrResult(*SET_STRING_WITH_QUERY)(SrdXrSessionHandle, const char*, const char*);
            typedef SrdXrResult(*GET_VIEWPOINT_COMPOSITOR_PARAMS)(SrdXrSessionHandle, SrdXrViewpointCompositorParams*);
            typedef SrdXrResult(*SET_VIEWPOINT_COMPOSITOR_PARAMS)(SrdXrSessionHandle, const SrdXrViewpointCompositorParams*);

            struct Library {
                CREATE_SESSION create_session;
                DESTROY_SESSIOM destroy_session;
                BEGIN_SESSIOM begin_session;
                END_SESSIOM end_session;
                POLL_EVENT poll_event;
                BEGIN_FRAME begin_frame;
                END_FRAME end_frame;
                LOCATE_VIEWS locate_views;

                /* extension API */
                GET_PLATFORM_SPECIFIC_DATA get_platform_specific_data;
                GET_PROJECTIOM_MATRIX get_projection_matrix;
                SET_CLIPPING_DISTANCE set_clipping_distance;
                SET_GRAPHICS_API set_graphics_api;
                SET_RENDER_DEVICE set_render_device;
                GENERATE_TEXTURE_AND_SHADERS generate_texture_and_shaders;

                ENUMERATE_DEVICES enumerate_devices;
                GET_DEVICE get_device;
                GET_DEVICE_STATE get_device_state;

                LOCATE_DISPLAY locate_display;

                SET_DEBUG_LOG_CALLBACK set_debug_log_callback;

                GET_CROSSTALK_CORRECTION_SETTINGS get_crosstalk_correction_settings;
                SET_CROSSTALK_CORRECTION_SETTINGS set_crosstalk_correction_settings;
                GET_CROSSTALK_CORRECTION_SETTINGS_V1_1_0 get_crosstalk_correction_settings_v1_1_0;
                SET_CROSSTALK_CORRECTION_SETTINGS_V1_1_0 set_crosstalk_correction_settings_v1_1_0;
                GET_CROSSTALK_CORRECTION_SYSTEM_SETTINGS get_crosstalk_correction_system_settings;
                SET_CROSSTALK_CORRECTION_SYSTEM_SETTINGS set_crosstalk_correction_system_settings;
                SET_COLOR_MANAGEMENT_SETTINGS set_color_management_settings;
                ENABLE_TEMPERATURE_COMPENSATION enable_temperature_compensation;

                SAVE_USER_SETTINGS save_user_settings;
                GET_CAMERA_SETTINGS get_camera_settings;
                SET_CAMERA_SETTINGS set_camera_settings;
                GET_CAMERA_GAIN get_camera_gain;
                SET_CAMERA_GAIN set_camera_gain;
                SHOW_CAPTURED_IMAGE_WINDOW show_captured_image_window;
                GET_PERFORMANCE_MODE get_performance_mode;
                SET_PERFORMANCE_MODE set_performance_mode;

                PAUSE_HEAD_TRACKING pause_head_traking;
                RESUME_HEAD_TRACKING resume_head_traking;

                /* Debug API */
                GET_FLOAT_WITH_QUERY get_float_with_query;
                SET_FLOAT_WITH_QUERY set_float_with_query;
                GET_INT_WITH_QUERY get_int_with_query;
                SET_INT_WITH_QUERY set_int_with_query;
                GET_STRING_WITH_QUERY get_string_with_query;
                SET_STRING_WITH_QUERY set_string_with_query;
                GET_VIEWPOINT_COMPOSITOR_PARAMS get_viewpoint_compositor_params;
                SET_VIEWPOINT_COMPOSITOR_PARAMS set_viewpoint_compositor_params;
            };

            std::unique_ptr<Library> LinkXrLibraryWin64();
            void UnlinkXrLibraryWin64();

        } // namespace utility
    } // namespace xr
} // namespace srd

#endif // LOAD_LIBRARY_UTILITY_H_
