#ifndef __PSSDK__
#define __PSSDK__

//#include <Windows.h>
#include "pstypes.h"

//***************
// Types
//***************

// CameraManager identifier. CameraManager performs cameras interaction and
// communication
typedef void* PSCameraManagerHandle;
// General subscriber identifier. This handler should be released by PSFree
typedef void* PSSubscriberHandle;
// Camera session identifier. This handler should be released by PSFree
typedef void* PSSessionHandle;
// Camera identifier
typedef int PSCameraId;

#define PS_MAX_NAME_LEN         128
#define PS_MAX_SYSTEMID_LEN     256
#define PS_MAX_PSMVER_LEN       256
#define PS_MAX_SERIAL_LEN       64

struct
PSCameraInfo
{
    // unique camera identifier
    PSCameraId  id;
    // camera name (model)
    wchar_t     name[PS_MAX_NAME_LEN];
    // camera system identifier
    wchar_t     systemId[PS_MAX_SYSTEMID_LEN];
    // camera firmware version
    wchar_t     psmVersion[PS_MAX_PSMVER_LEN];
    // camera serial number
    wchar_t     serialNumber[PS_MAX_SERIAL_LEN];
};

// Values of camera connection state used in PSCameraListChangedCallback
enum
PSCameraConnectionState
{
    PS_CS_CONNECTED,
    PS_CS_DISCONNECTED,
};

// Values of preview state used in PSSetPreviewState/PSGetPreviewState
enum
PSPreviewState
{
    PS_PREVIEW_DISABLED,
    PS_PREVIEW_ENABLED
};

#ifdef _WIN32
#define PATH_CHAR wchar_t
#else
#define PATH_CHAR char
#endif

// Callback function for PSCameraListChanged event
// in case camera connected or disconnected from system
// Argument list:
//      context -       user data given to the SDK in
//                      PSCameraListChangedSubscribe call
//      devInfo -       information about camera issued change in the camera
//                      list. This pointer should be released by
//                      PSFree function.
//      connectionState -   PS_CS_CONNECTED or PS_CS_DISCONNECTED
typedef void (PSSTDCALL *
PSCameraListChangedCallback)(void* context, PSCameraInfo* devInfo,
    int connectionState);

// Callback function for PSCameraInitializationError event
// Argument list:
//      context -       user data given to the SDK in
//                      PSCameraInitializationErrorSubscribe  call
//      code -          error code of PSResult type
//      camSystemId -   camera system identifier which initialization raised the
//                      error. This handler should be released by PSFree command
typedef void (PSSTDCALL *
PSCameraInitializationErrorCallback)(void* context, int code,
    wchar_t* camSystemId);

// Callback function for generic events which doesnt receive additional
// arguments. Used in several Subscribe functions
// Argument list:
//      context -  user data given to the SDK in event subscription command
typedef void (PSSTDCALL *
PSGenericEventCallback)(void* context);

// Callback function for PSCameraErrorSubscribe event
// Argument list:
//      context -   user data given to the SDK in PSDownloadCompletedSubscribe
//      code -      error code of PSResult type
typedef void (PSSTDCALL *
PSCameraErrorCallback)(void* context, PSResult code);

// Callback function for PSShootAsync/PSStopVideoAsync functions
// Argument list:
//      context -       user data
//      resFileInfo -   information about  taken image file. This handle should
//                      be released by PSFree function
typedef void (PSSTDCALL *
PSNewFileAsyncCallback)(void* context, PSFileInfo* resFileInfo);

// Callback function for PSDownloadFileToAsync event
// Argument list:
//      context -   user data
//      fileId -    downloaded file identifier
typedef void (PSSTDCALL *
PSDownloadFileToAsyncCallback)(void* context, PSFileId fileId);

// Callback function for PSPropertyChanged event.
// Function should be defined in client application and
// given to PSPropertyChangedSubscribe function as an argument.
// Argument list:
//      context -   user data given to the SDK in
//                  PSPropertyChangedSubscribe call
//      prop -      identifier of changed property
typedef void (PSSTDCALL *
PSPropertyChangedCallback)(void* context, int prop);

//***************
// Functions
//***************

// Initialization of the SDK, should be called before using SDK functions
// Before initialization PS-SDK functions behavior is not defined
extern "C"
PSResult PSSDKAPI
PSInitializeSDK(const PATH_CHAR* inConfigPath = 0);

// Closes SDK and releases all resources allocated by SDK
// Note:
//      All allocated by application SDK handles and resources
//      must be released with PSFree command prior to PSTerminateSDK.
//      PS SDK will not be terminated until application release all resources.
extern "C"
void PSSDKAPI
PSTerminateSDK();

// Get PS-SDK version
extern "C"
void PSSDKAPI
PSGetSDKVersion(const wchar_t** outSDKVersion);

// Removes object by given link from the memory. Could receive any object of
// PS-SDK. Correctly accepts null pointers.
extern "C" PSPUBLIC
void PSSDKAPI
PSFree(void*);

// Returns CameraManager object, CameraManager initialization.
// CameraManager performs cameras interaction and communication.
// To release memory from CameraManager instance, use PSFree command on
// CameraManagerHandle
extern "C"
PSCameraManagerHandle PSSDKAPI
PSGetCameraManager();

// Registers callback function for camera list changing event
// Events contains information on their type (connection or disconnection a
// camera from the list)
// Argument list - input:
//      inCamMgr -      current CameraManager identifier
//      inCallback -    callback function to register
//      inContext -     user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSCameraListChangedSubscribe(PSCameraManagerHandle inCamMgr,
    PSCameraListChangedCallback inCallback, void* inContext);

// Registers callback function for camera initialization error event
// Argument list - input:
//      inCamMgr -   current CameraManager identifier
//      inCallback -   callback function to register
//      inContext -    user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSCameraInitializationErrorSubscribe(PSCameraManagerHandle inCamMgr,
    PSCameraInitializationErrorCallback inCallback, void* inContext);

// Returns list of compatible cameras connected to the system. Camera list is a
// collection of structure of CameraInfo type.
// Argument list - input:
//      inCamMgr -      current CameraManager identifier
// Argument list - output:
//      outCameraList - list of PSCameraInfo items with descriptions of
//                      connected cameras. Memory should be released by PSFree
//                      command.
//      outListSize -   number of items in list
// Note:
//      outCameraList is NULL if there is no connected cameras
extern "C"
void PSSDKAPI
PSGetCameraList(PSCameraManagerHandle inCamMgr, PSCameraInfo** outCameraList,
    int* outListSize);

// Opens session of camera remote control by CameraId
// Argument list - input:
//      inCamMgr -    current CameraManager identifier
//      inCamId -     camera identifier from PSCameraInfo
// Argument list - output:
//      outSession -    session handler if successful
// Note:
//      to close session release this handler with PSFree function
extern "C"
PSResult PSSDKAPI
PSOpenSession(PSCameraManagerHandle inCamMgr, PSCameraId inCamId,
    PSSessionHandle* outSession);

// Returns cameras info by its opened session handler
// Argument list - input:
//      inSession -     opened camera session identifier
// Return value:
//      outInfo -       PSCameraInfo object
extern "C"
PSResult PSSDKAPI
PSGetCameraInfo(PSSessionHandle inSession, PSCameraInfo* outInfo);

// Checks if the camera still connected in the session
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outCameraConnectionState -
//                      PS_CS_CONNECTED or PS_CS_DISCONNECTED
extern "C"
PSResult PSSDKAPI
PSGetCameraConnectionState(PSSessionHandle inSession,
    int* outCameraConnectionState);

// Registers callback function for event of camera error
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register
//      inContext -     user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSCameraErrorSubscribe(PSSessionHandle inSession,
    PSCameraErrorCallback inCallback, void* inContext);

// Starts and stops receiving preview image from camera viewfinder
// Argument list - input:
//      inSession -     opened camera session identifier
//      inState -
//          PS_PREVIEW_ENABLED - starts preview
//          PS_PREVIEW_DISABLED - stops preview
// Note:
//      receiving preview significantly increases system resources usage
extern "C"
PSResult PSSDKAPI
PSSetPreviewState(PSSessionHandle inSession, int inState);

// Returns current state of receiving preview images from the camera viewfinder
// Argument list - input:
//      inSession -    opened camera session identifier
// Argument list - output:
//      outState -
//          PS_PREVIEW_ENABLED - preview enabled
//          PS_PREVIEW_DISABLED - preview disabled
extern "C"
PSResult PSSDKAPI
PSGetPreviewState(PSSessionHandle inSession, int* outState);

// Registers callback function for event of creating new preview image from the
// camera viewfinder
// Argument list - input:
//      inSession -   opened camera session identifier
//      inCallback -   callback function to register
//      inContext -    user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
// Note:
//       this event occures every time new frame is ready
//       to get new frame data use PSGetPreviewFrame
extern "C"
PSSubscriberHandle PSSDKAPI
PSNewPreviewFrameSubscribe(PSSessionHandle inSession,
    PSGenericEventCallback inCallback, void* inContext);

// Get preview frame data from the camera viewfinder
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outBMPData -    image data in BMP-file format (BITMAPFILEHEADER,
//                      BITMAPINFOHEADER, array of pixels). To release memory
//                      from array PSFree command should be used;
//      outDataSize -   size of outBMPData in bytes
// Attention!
//      You must release previous frame with PSFree prior to get new frame or
//      error occures.
extern "C"
PSResult PSSDKAPI
PSGetPreviewFrame(PSSessionHandle inSession, void** outBMPData,
    int* outDataSize);

// Sends a shoot command to the camera
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outFileInfo -   information about  taken image file.
extern "C"
PSResult PSSDKAPI
PSShoot(PSSessionHandle inSession, PSFileInfo* outFileInfo);

// Sends a shoot command to the camera
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register of PSGenericEventCallback
//                      type. Executed after file download has completed.
//      inContext -     user data to be passed to callback function
extern "C"
PSResult PSSDKAPI
PSShootAsync(PSSessionHandle inSession, PSNewFileAsyncCallback inCallback,
    void* inContext);

// Returns current list of image files on camera flash memory card taken during
// current session
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outList -       list of PSFileInfo items for all taken image files.
//                      Memory should be released from the list after its using
//                      by PSFree command
//      outListSize -   number of items in list
extern "C"
PSResult PSSDKAPI
PSGetFileList(PSSessionHandle inSession, PSFileInfo** outList,
    int* outListSize);

// Download image file from the memory card to given path including file name
// Argument list - input:
//      inSession -     opened camera session identifier
//      inFileId -      identifier of transferring file in file list
//      inFilePath -    full path with file name for saving downloaded file
//      inRemoveFile -  allows delete file after download. PS_TRUE - to delete
//                      file, PS_FALSE - file stays on card
//      inCallback -    callback function to register of PSGenericEventCallback
//                      type. Executed after file download has completed.
//      inContext -     user data to be passed to callback function
// Note:
//      If you choose not to delete image file automatically use PSDeleteFile
//      command to remove it from camera card. All files automatiaclly removed
//      from card during session start and close.
extern "C"
PSResult PSSDKAPI
PSDownloadFileToAsync(PSSessionHandle inSession, PSFileId inFileId,
    wchar_t* inFilePath, int inRemoveFile,
    PSDownloadFileToAsyncCallback inCallback, void* inContext);

// Download image file from the memory card to given path including file name
// Argument list - input:
//      inSession -     opened camera session identifier
//      inFileId -      identifier of transferring file in file list
//      inFilePath -    full path with file name for saving downloaded file
//      inRemoveFile -  allows delete file after download. PS_TRUE - to delete
//                      file, PS_FALSE - file stays on card
// Note:
//      If you choose not to delete image file automatically use PSDeleteFile
//      command to remove it from camera card. All files automatiaclly removed
//      from card during session start and close.
extern "C"
PSResult PSSDKAPI
PSDownloadFileTo(PSSessionHandle inSession, PSFileId inFileId,
    wchar_t* inFilePath, int inRemoveFile);

// Deletes file from the camera memory card
// Argument list - input:
//      inSession -     opened camera session identifier
//      inFileId -      identifier of transferring file in file list
extern "C"
PSResult PSSDKAPI
PSDeleteFile(PSSessionHandle inSession, PSFileId inFileId);

// Performs reset the auto exposure (AE) and auto focus (AF)
// Argument list - input:
//      inSession -     opened camera session identifier
extern "C"
PSResult PSSDKAPI
PSUpdateAEAF(PSSessionHandle inSession);

// Power off camera
// Argument list - input:
//      inSession -     opened camera session identifier
extern "C"
PSResult PSSDKAPI
PSPowerDown(PSSessionHandle inSession);

// Returns maximum available optical zoom value
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outMaxZoom -    maximum available zoom value
extern "C"
PSResult PSSDKAPI
PSGetMaximumZoom(PSSessionHandle inSession, int* outMaxZoom);

// Returns current optical zoom value
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outZoom -       current zoom value
extern "C"
PSResult PSSDKAPI
PSGetZoom(PSSessionHandle inSession, int* outZoom);

// Move zoom to given value
// Argument list - input:
//      inSession -     opened camera session identifier
//      inZoom -
// Note:
//      The function sends to the camera command to change zoom value and
//      finishes immediately.
extern "C"
PSResult PSSDKAPI
PSSetZoom(PSSessionHandle inSession, int inZoom);

// Registers callback function for event of changing current zoom value
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register of PSGenericEventCallback
//                      type
//      inContext -     user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSZoomChangedSubscribe(PSSessionHandle inSession,
    PSGenericEventCallback inCallback, void* inContext);

#include "psproperty.h"

// Returns readable name for given property
// Argument list - input:
//      inProp -        property identifier
// Argument list - output:
//      outName -       property name. Handlers release is not necessary
extern "C"
PSResult PSSDKAPI
PSGetPropertyName(int inProp, const char** outName);

// Returns readable name for given value of given property
// Argument list - input:
//      inProp -        property identifier
//      inPropVal -     property value identifier
// Argument list - output:
//      outName -      property value name. Handlers release is not necessary.
extern "C"
PSResult PSSDKAPI
PSGetPropertyValName(int inProp, int inPropVal, const char** outName);

// Returns list of all available properties.
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outList -       list of available properties
//                      Memory should be released from the list after its using
//                      by PSFree command
//      listLen -       length of outList list
// Note:
//      Notice that list contains only currently available properties.
//      It could be changed in dependence of current camera state, camera
//      shooting mode and other properties values
extern "C"
PSResult PSSDKAPI
PSGetPropertyList(PSSessionHandle inSession, int** outList, int* listLen);

// Returns description of given property
// Argument list - input:
//      inSession -     opened camera session identifier
//      inProp -        property identifier
// Argument list - output:
//      outDesc -       property description of the PSProp_Desc type
//                      This handler should be released by PSFree
// Note:
//      Notice that resulting PSProp_Desc structure availableValues list
//      contains only values available at the moment. The list could be changed
//      in dependence of current camera state, camera shooting mode and other
//      properties values
extern "C"
PSResult PSSDKAPI
PSGetPropertyDesc(PSSessionHandle inSession, int inProp, PSProp_Desc** outDesc);

// Returns current value of given property
// Argument list - input:
//      inSession -     opened camera session identifier
//      inProp -        property identifier
// Argument list - output:
//      outRes -        current property value
extern "C"
PSResult PSSDKAPI
PSGetPropertyData(PSSessionHandle inSession, int inProp, int* outRes);

// Sets value for given property
// Argument list - input:
//      inSession -     opened camera session identifier
//      inProp -        property identifier
//      inVal -         new property value
extern "C"
PSResult PSSDKAPI
PSSetPropertyData(PSSessionHandle inSession, int inProp, int inVal);

// Registers callback function for event of properties list changed
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register of PSGenericEventCallback
//                      type
//      inContext -     user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSPropertyListChangedSubscribe(PSSessionHandle inSession,
    PSGenericEventCallback inCallback, void* inContext);

// Registers callback function for event of property change
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register of
//                      PSPropertyChangedCallback type
//      inContext -     user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSPropertyChangedSubscribe(PSSessionHandle inSession,
    PSPropertyChangedCallback inCallback, void* inContext);

// Registers callback function for event of changing focus value in manual
// focus mode
// Argument list - input:
//      inSession -    opened camera session identifier
//      inCallback -   callback function to register
//      inContext -    user data to be passed to callback function
// Return value:
//      Subscription handler or NULL if error occurs
//      To unsubscribe release this handler with PSFree function
extern "C"
PSSubscriberHandle PSSDKAPI
PSFocusChangedSubscribe(PSSessionHandle inSession,
    PSGenericEventCallback inCallback, void* inContext);

// Returns current focus value in manual focus mode
// Argument list - input:
//      inSession -     opened camera session identifier
// Argument list - output:
//      outDistance -   current focus distance value
extern "C"
PSResult PSSDKAPI
PSGetFocus(PSSessionHandle inSession, int* outDistance);

// Move focus to given value in manual focus mode
// Argument list - input:
//      inSession -     opened camera session identifier
//      inDistance -    new distance value
// Note:
//      The function can be used only if ManualFocusMode property is set to On.
//  Use -1 for infinity value, distance value is measured in millimeters
extern "C"
PSResult PSSDKAPI
PSSetFocus(PSSessionHandle inSession, int inDistance);

// Move focus in manual focus mode by step (exact next or previous value)
// Argument list - input:
//      inSession -     opened camera session identifier
//      inShift -       +1, -1, +2, -2 etc.
// Note:
//      The function can be used only if ManualFocusMode property is set to On.
//  The function can be used for manual control of focusing distance, moving
//  focus value to exact next or previous supported value.
extern "C"
PSResult PSSDKAPI
PSFocusShift(PSSessionHandle inSession, int inShift);

// Check if video mode supported
// Argument list - input:
//      inSession -     opened camera session identifier
// Return value:
//      PS_TRUE - video mode supported
//      PS_FALSE - video mode unsupported
extern "C"
int PSSDKAPI
PSIsVideoSupported(PSSessionHandle inSession);

// Turn video recording on
// Argument list - input:
//      inSession -     opened camera session identifier
extern "C"
PSResult PSSDKAPI
PSStartVideo(PSSessionHandle inSession);

// Turn video recording off
// Argument list - input:
//      inSession -     opened camera session identifier
// Return value:
//      outVideoFile -  information about  taken video file.
//                      File can be downloaded using the PSDownloadFile and
//                      PSDownloadFileToAsync function.
extern "C"
PSResult PSSDKAPI
PSStopVideo(PSSessionHandle inSession, PSFileInfo* outFileInfo);

// Turn video recording off
// Argument list - input:
//      inSession -     opened camera session identifier
//      inCallback -    callback function to register of PSGenericEventCallback
//                      type. Executed after shoot on camera has completed.
//      inContext -     user data to be passed to callback function
extern "C"
PSResult PSSDKAPI
PSStopVideoAsync(PSSessionHandle inSession, PSNewFileAsyncCallback inCallback,
    void* inContext);

// Set application license identifier for activation
// Argument list:
//      inAppId - application license identifier
// Note:
//      It is not mandatory to use it for license activation.
//      If PSSetApplicationID is not used in application, then
//      default value with full path to PS-SDK dll's used.
extern "C"
void PSSDKAPI
PSSetApplicationID(wchar_t* inAppId);

// Get application license identifier of activated application
// Argument:
//      outApplicationID -  current application license identifier for activated
//                          application
//      This handler should be released by PSFree command
extern "C"
void PSSDKAPI
PSGetApplicationID(wchar_t** outApplicationID);

// Checks activation server status
// Return value:
//      PS_TRUE - activation server available
//      PS_FALSE - activation server not available
extern "C"
int PSSDKAPI
PSIsActivationServerAvailable();

// Performs online activation
// Argument list - input:
//      inSerialNumber - license serial number
// Return value:
//      PS_OK - activation completed successfully
//      PS_INVALID_SERIAL_NUMBER - license serial number is invalid
//      PS_FAILED - serial number valid but activation failed, please contact
//                  support
//      PS_ACTIVATION_SERVER_UNAVAILABLE - activation server not available,
//                                         perform offline activation
// Linux Only Note:
//      Check appropriate read/write permissions on /var/PSSDK/ folder for
//      storing activation data. Activation fails on any activation data file
//      creation, read or write errors.

extern "C"
PSResult PSSDKAPI
PSPerformOnlineActivation(const wchar_t* inSerialNumber);

// Generates activation key by serial number (for offline activation only)
// Argument list - input:
//      inSerialNumber - license serial number
// Argument list - output:
//      outActivationKey -   activation number, this pointer
//                            should be released by PSFree command
extern "C"
PSResult PSSDKAPI
PSGetActivationKey(wchar_t* inSerialNumber, wchar_t** outActivationKey);

// Get offline activation server URL (for offline activation only)
// Argument list - output:
//      outURL -   offline activation server URL
// Note:
//      Provide user with this link to perform offline activation
//      from any other system with internet connection.
extern "C"
void PSSDKAPI
PSGetOfflineActivationServerURL(const wchar_t** outURL);

// Performs offline activation (no internet connection required)
// Argument list - input:
//      inSerialNumber - license serial number
//      inAuthKey - authorization key (provided to user from offline activation
//                  server)
// Return value:
//      PS_OK - activation completed successfully
//      PS_INVALID_SERIAL_NUMBER - license serial number is invalid
//      PS_FAILED - activation failed, invalid authorization key, please contact
//                  support
extern "C"
PSResult PSSDKAPI
PSPerformOfflineActivation(wchar_t* inSerialNumber, wchar_t* inAuthKey);

// Checks PS-SDK activation status
// Return value:
//      PS_TRUE - PS-SDK activated, full mode
//      PS_FALSE - PS-SDK not activated, demo mode
extern "C"
int PSSDKAPI
PSIsSDKActivated();

// Get license serial number for activated PS-SDK
// Argument list - output:
//      outSerialNumber -   license serial number. This handler should be
//                          released by PSFree command
// Return value:
//      PS_OK - success
//      PS_FAILED - PS-SDK not activated
extern "C"
PSResult PSSDKAPI
PSGetSerialNumber(wchar_t** outSerialNumber);

// Reset activated status for application, SDK will be switched to demo mode
extern "C"
void PSSDKAPI
PSResetActivation();

#endif // __PSSDK__
