// ----------------------------------------------------------------------------
//  <copyright file="ScreenPro.h" company="Global Graphics Software Ltd">
//      Copyright (c) 2020 Global Graphics Software Ltd. All rights reserved.
//  </copyright>
// -----------------------------------------------------------------------------

#ifndef __SCREENPRO_H__
#define __SCREENPRO_H__
/**
* @file    ScreenPro.h
* @brief   This header declares the ScreenPro API.
*
*          The general flow to calling the APIs is as follows:
*
*          1. ScreenProStartup(...)
*          2. ScreenProScreen(...)
*          3. ScreenProShutdown(...)
*
*          There are other methods to query screen or licensing.  To understand when to call this function,
*          see the documentation for each method.
*
*/

#include <stdint.h>
#include <stdbool.h>

#ifdef _WIN32
#ifdef SCREENPRODLL_EXPORTS
#define SCREENPRO_API __declspec(dllexport)
#else
#define SCREENPRO_API __declspec(dllimport)
#endif
#else
#define SCREENPRO_API
#endif

#define MAX_PRINTFLATSUBSCRIPTION   1024
#define MAX_OEMID                   64
#define MAX_EXPIRYDATE              16
#define MAX_VERSION                 16

#ifdef __cplusplus
extern "C"
{
#endif

/**
  * @brief Pointer to user-defined opaque data, which should uniquely identify an open file.
  */
typedef void* IOHandle;

/**
 * @brief  Structure containing the functions to use for file I/O. (E.g. Used when reading tile data.)
 */
typedef struct ScreenProFileIO
{
    /**
     * @brief  Open the named file.
     *
     * @param filename  The name of the file to open.
     * @return a unique handle (or NULL on failure).
     */
    IOHandle (*openr)(const char* filename);

    /**
     * @brief  Read data from an open file.
     *
     * @param handle     The handle to an open file.
     * @param dest       Pointer to a memory location to fill with data.
     * @param byteCount  The (maximum) number of bytes to read.
     * @return The actual number of bytes read.
     */

    size_t (*read)(IOHandle handle, void* dest, size_t byteCount);

    /**
     * @brief  Close an open file handle.
     * @param  The handle to close. (Note: Should be set to NULL by this call.)
     */
    void (*close)(IOHandle handle);

    /**
     * @brief  Get the file size.
     *
     * @param filename  The name of the file.
     * @return the file size.
     */
    size_t (*filesize)(const char *filename);
} ScreenProFileIO;

/**
 * @brief   A representation of a raster, including the raster data and how it's packaged.
 */
typedef struct ScreenProRaster
{
    /**
     * @brief Size of the structure
     */
    size_t structSize;
    
    /**
     * @brief X-dimension of image in pixels.
     */
    uint64_t width;

    /**
     * @brief Y-dimension of image in pixels.
     */
    uint64_t height;

    /**
     * @brief Step in bytes from one line to the next.
     */
    uint64_t stride;

    /**
     * @brief How many bits in a pixel. Only supported input values are 8 and 16.
     */
    uint64_t bitsPerPixel;

    /**
     * @brief Pointer to contone data, screened in-place.
     */
    void *buffer;
} ScreenProRaster;

 /**
  * @brief    Offsets within a raster.
  */
typedef struct ScreenProOffset
{
    /**
     * @brief X Offset:
     *        Offset in the X (raster width) direction of the input raster in relation to the output device.
     *        Currently supported for Mirror, Pearl and Chameleon.
     */
    uint64_t x;

    /**
     * @brief Y Offset:
     *        Offset in the Y (raster height) direction of the input raster in relation to the output device.
     *        Currently supported for Mirror, Pearl and Chameleon.
     */
    uint64_t y;
} ScreenProOffset;


/**
 * @brief   Set of justifications when applying calibration.
 */
typedef enum CalibrationJustification
{
    /**
     * @brief   Justified at left.
     */
    CALIBRATION_LEFT = 0,

    /**
     * @brief   Justified at center.
     */
     CALIBRATION_CENTER = 1,

     /**
      * @brief   Justified at right.
      */
     CALIBRATION_RIGHT = 2
} CalibrationJustification;

/**
* @brief    Calibration option.
*/
typedef struct CalibrationOption
{
    /**
     * @brief Justification when applying calibration.
     */
    CalibrationJustification justification;

    /**
     * @brief Edge offset in case of left or right justification.
     */
    uint64_t edgeOffset;

    /**
     * @brief Is calibration rotated a further 90 degrees w.r.t. image.
     */
    bool calibrationRotate90;
} CalibrationOption;

/**
 * @brief   Set of screening layout information.
 */
typedef struct ScreenProLayout
{
    /**
     * @brief Size of the structure
     */
    size_t structSize;

    /**
     * @brief Separation or channel index for screening.
     */
    uint64_t channelNumber;

    /**
     * @brief Offset between image and screen spaces.
     */
    ScreenProOffset screenOffset;

    /**
     * @brief Is screen-space rotated a further 90 degrees w.r.t. image.
     */
    bool screenRotate90;

    /**
     * @brief Calibration option
     */
    CalibrationOption calibrationOption;
} ScreenProLayout;

/**
 * @brief   The type of screening method.
 */
typedef enum ScreenProScreenType
{
    /**
     * @brief   Not for public use.
     */
    SP_NOSCREEN = 0,

    /**
     * @brief    A screening method that uses a combination of error diffusion and
     *           Chameleon tiles. Also known as error diffusion hybrid.
     */
    SP_CHIMERA,

    /**
     * @brief    A screening method that uses Chameleon tiles.
     */
    SP_CHAMELEON,

    /**
     * @brief    Mirror screening method. 
     */
    SP_MIRROR,

    /**
     * @brief    Pearl screening method. 
     */
    SP_PEARL,

    /**
     * @brief    Posterize screening method.
     */
    SP_POSTERIZE,

    /**
     * @brief	Opal screening method.
     */
    SP_OPAL,
    
    /**
     * @brief	Custom screening method.
     */
    SP_CUSTOM
} ScreenProScreenType;

 /**
  * @brief   Basic information describing screen characteristics for each channel.
  */
typedef struct ScreenProScreenInfo
{
    /**
     * @brief    The type of screen.
     */
    ScreenProScreenType screenType;

    /**
     * @brief    The number of droplet sizes, not including zero.
     */
    uint64_t     maxDrops; 
} ScreenProScreenInfo;

 /**
  * @brief   Set of features that have been enabled by licensing.
  */
typedef struct ScreenProLicenseInfo
{
    /**
     * @brief    Maximum screening threads allowed.
     */
    int32_t maxThreads;

    /**
     * @brief    Whether PrintFlat calibration is enabled.
     */
    bool printFlatAllowed;

    /**
     * @brief    Whether unencrypted calibrations allowed.
     */
    bool unencryptedCalibrations;

    /**
     * @brief    Whether unencrypted HDS files allowed.
     */
    bool unencryptedHDS;
} ScreenProLicenseInfo;

 /**
  * @brief   Record of all the input permission keys for use in licensing.
  */
typedef struct ScreenProPermit
{
    /**
     * @brief   The license key, if provided.
     */
    char *license;

    /**
     * @brief   The password, if provided.
     */
    char *password;

    /**
     * @brief   The number of output boards present.
     */
    int32_t outputBoards;

    /**
     * @brief   OEM Id for PrintFlat.
     */
    char *oemId;

    /**
     * @brief   Expiry date for PrintFlat.
     */
    char *expiryDate;
} ScreenProPermit;

/*
 * Structure holding permit information for generating PrintFlat subscription.
 */
typedef struct PrintFlatSubscription
{
    /**
     * @brief Version
     */
    char version[MAX_VERSION];

    /**
     * @brief OEM ID
     */
    char oemId[MAX_OEMID];

    /**
     * @brief Expiry date
     */
    char expiryDate[MAX_EXPIRYDATE];

    /**
     * @brief Encrypted subscription string
     */
    char subscription[MAX_PRINTFLATSUBSCRIPTION];
} PrintFlatSubscription;

/**
 * Result of a ScreenPro API call.
 */
typedef enum ScreenProResult
{
    /**
     * @brief   Success.
     */
    SP_SUCCESS = 0,

    /**
     * @brief   Failed to allocate required memory.
     */
    SP_MEMORY_ERR = 1,

    /**
     * @brief   Unsupported or invalid arguments.
     */
    SP_INVALID_ARGS = 2,

    /**
     * @brief   Missing of zero-size Toml config file.
     */
    SP_NO_TOML_FILE = 3,

    /**
     * @brief   Failed to open the given file.
     */
    SP_FILE_OPEN_ERR = 4,

    /**
     * @brief   Failed to read from the given file.
     */
    SP_FILE_READ_ERR = 5,

    /**
     * @brief   Failed to write to the given file.
     */
    SP_FILE_WRITE_ERR = 6,

    /**
     * @brief   Toml file syntax error.
     */
    SP_TOML_SYNTAX_ERR = 7,

    /**
     * @brief   API call has been made in the wrong context.
     */
    SP_INVALID_CALL = 8,

    /**
     * @brief   Toml key not recognized.
     */
    SP_UNKNOWN_TOML_KEY = 9,

    /**
     * @brief   Max number of screensets exceeded.
     */
    SP_TOO_MANY_SCREENSETS = 10,

    /**
     * @brief   Incorrect size of structure.
     */
    SP_INVALID_STRUCT_SIZE = 11,

    /**
     * @brief   Invalid screentype selected.
     */
    SP_BAD_SCREENTYPE = 12,

    /**
     * @brief   Missing or zero-size tile file (.bin).
     */
    SP_NO_BINFILE = 13,

    /**
     * @brief  Tile file (.bin) has incorrect syntax
     */
    SP_BINFILE_SYNTAX_ERR = 14,

    /**
     * @brief  Missing or zero-size ".dat" file.
     */
    SP_NO_DATFILE = 15,

    /**
     * @brief  ".dat" file has incorrect syntax
     */
    SP_DATFILE_SYNTAX_ERR = 16,

    /**
     * @brief  Error when decrypting web calibration.
     */
    SP_DECRYPT_ERR = 17,

    /**
     * @brief  Screening with an invalid channel.
     */
    SP_BAD_CHANNEL = 18,

    /**
     * @brief  Error in licensing.
     */
    SP_LICENSE_ERR = 19, 

    /**
     * @brief  PFC file error.
     */
    SP_PFC_ERR = 20,

    /**
     * @brief  Error when encrypting a string/file.
     */
    SP_ENCRYPT_ERR = 21,

    /**
     * @brief  One or more time limited licenses have expired.
     */
    SP_LICENSE_EXPIRED = 22,

    /**
     * @brief  Not for public use. Must be last.
     */
    SP_MAX_ERRCODE = 23, 
} ScreenProResult;

/**
 * @brief   Startup the ScreenPro library.
 *
 * @param[in] startupFilename  Optional startup TOML configuration file.
 * @param[in] fileIO           Optional table of file IO functions pointers.
 * @param[in] permit           Optional structure of permission data.
 * @return                     Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProStartup(const char *startupFilename,
                                               const ScreenProFileIO *fileIO,
                                               const ScreenProPermit *permit);

/**
 * @brief   Screen a raster of memory in place.
 *
 * @param[in]     screensetFolder  Folder containing the screen definition.
 * @param[in,out] raster           Definition of the memory raster.
 * @param[in]     layout           Channel and offsets for screening operation.
 * @return                         Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProScreen(const char *screensetFolder,
                                              ScreenProRaster *raster,
                                              ScreenProLayout *layout);

/**
 * @brief   Scale and screen a raster.
 *
 * @param[in] screensetFolder  Folder containing the screen definition.
 * @param[in] sourceRaster     Definition of the source contone raster.
 * @param[in,out] destRaster   Definition of the destination halftone raster.
 * @param[in] layout           Channel and offsets for screening operation.
 * @return                     Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProScaleAndScreen(
                                            const char *screensetFolder,
                                            ScreenProRaster *sourceRaster,
                                            ScreenProRaster *destRaster,
                                            ScreenProLayout *layout);

/**
 * @brief   Query the configuration of a given screenset.
 *
 * @param[in]  screensetFolder  Folder containing the screen definition.
 * @param[in]  channelNumber    Which channel to query.
 * @param[out] info             Resulting screening information.
 * @return                      Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProQueryScreen(const char *screensetFolder,
                                                   uint64_t channelNumber,
                                                   ScreenProScreenInfo *info);

/**
 * @brief Query the functionality allowed by licensing.
 *
 * @param[out] info   Resulting licensing information.
 * @return            Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProQueryLicensing(ScreenProLicenseInfo *info);

/**
 * @brief Count the distribution of drop levels within the raster.
 *
 * @param[in]  raster  Raster for which drops are to be counted.
 * @param[out] counts  Resulting distribution of drop counts.
 * @return             Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProCountDrops(ScreenProRaster *raster,
                                                  uint64_t *counts);

/**
 * Shutdown the ScreenPro library.
 */
SCREENPRO_API ScreenProResult ScreenProShutdown(void);

/**
 * @brief Get the version string for the ScreenPro library.
 *
 * @return             The version string.
 */
SCREENPRO_API const char *ScreenProGetVersion();

/**
 * @brief Installs a PrintFlat calibration package into a Screen.
 *
 * Calling this function will install the calibration files and update
 * the config files for the Screen to use.
 * NB. currently only supported for Mirror/Pearl screening.
 *
 * @param   screensFolder  The folder containing the Screens for ScreenPro.
 * @param   fileName       The PrintFlat calibration package to install.
 * @param   isCalibration  If true, the package is calibration package, otherwise, it is linearization package.
 * @return                 Success or error code of the call.
 */
SCREENPRO_API ScreenProResult ScreenProInstallPfcPackage(const char *screensFolder, 
                                                         const char * fileName,
                                                         bool isCalibration);

/**
* @brief Get the PrintFlat subscription string for the ScreenPro library.
*
* @param[out] subscription  Pointer to a PrintFlatSubscription to return subscription details.
* 
* @return            Success or error code of the call.
*/
SCREENPRO_API ScreenProResult ScreenProGetPrintFlatSubscription(PrintFlatSubscription *subscription);

#ifdef __cplusplus
}
#endif

#endif /* __SCREENPRO_H__ */
