#ifndef __APPTOOLS_H__
#define __APPTOOLS_H__

#include "fio.h"
#include "bletools.h"

// ******************************************************************
// ****** Timer Functions *******************************************
// ******************************************************************

void StartTimer(unsigned long Duration);
void StopTimer(void);
bool TestTimer(void);

// ******************************************************************
// ****** Delay Function ********************************************
// ******************************************************************

void Delay(unsigned long Duration);

// ******************************************************************
// ****** Tools *****************************************************
// ******************************************************************

char Nibble2HexChar(byte Nibble);

// ******************************************************************
// ****** Beep Functions ********************************************
// ******************************************************************

void SetVolume(int NewVolume);
int GetVolume(void);
void BeepLow(void);
void BeepHigh(void);

// ******************************************************************
// ****** Compatibility to TWN3 *************************************
// ******************************************************************

int ConvertTagTypeToTWN3(int TagTypeTWN4);

// ******************************************************************
// ****** LEGIC Mini-API ********************************************
// ******************************************************************

bool LEGIC_Idle(void);
bool LEGIC_SearchTXP(int TagType,byte *ID,int *IDLength);
bool LEGIC_Select(int TagType);
bool LEGIC_ReadTagTypeFamily(int TagType,byte *Type,byte *Family);
bool LEGIC_SearchSegmentByStamp(const byte* Stamp,int StampLength);
bool LEGIC_SearchSegmentByIndex(int Index,byte *Stamp,int *StampLength,int *SegmentLength);
bool LEGIC_ReadSegment(int Offset,int ByteCnt,byte *Data);

// ******************************************************************
// ****** NFC *******************************************************
// ******************************************************************

typedef struct
{
    byte* Header;
    byte TypeLength;
    int PayloadLength;
    byte IDLength;
    byte* Type;
    byte* ID;
    byte* Payload;
    byte* NextRecord;
} TNDEFRecord;

#define NDEF_IsMBSet(Header)    (Header & 0x80)
#define NDEF_IsMESet(Header)    (Header & 0x40)
#define NDEF_IsCFSet(Header)    (Header & 0x20)
#define NDEF_IsSRSet(Header)    (Header & 0x10)
#define NDEF_IsILSet(Header)    (Header & 0x08)
#define NDEF_GetTNF(Header)        (Header & 0x07)

bool NDEF_WaitConnect(void);
bool NDEF_ReceiveRecord(byte *RecordType,int *RecordTypeLength,int MaxRecordTypeLength,
                        byte *RecordData,int *RecordDataLength,int MaxRecordDataLength);

// ******************************************************************
// ****** BLE *******************************************************
// ******************************************************************

#define LEN_MOBILE_ID        16

const char* BLEGetMessageString(int DecodedMessageType);
void BLECalcWalletKey(const byte *Source,byte *Dest);

// ******************************************************************
// ****** LED Compatibility Functions *******************************
// ******************************************************************

void CompLEDInit(int LEDs);
void CompLEDOn(int LEDs);
void CompLEDOff(int LEDs);
void CompLEDToggle(int LEDs);
void CompLEDBlink(int LEDs,int TimeOn,int TimeOff);

// ******************************************************************
// ****** Host Functions ********************************************
// ******************************************************************

#ifndef __FIO_H__

bool HostTestByte(void);
byte HostReadByte(void);
bool HostTestChar(void);
char HostReadChar(void);

void HostWriteByte(byte Byte);
void HostWriteChar(char Char);
void HostWriteString(const char *String);
void HostWriteRadix(const byte *ID,int BitCnt,int DigitCnt,int Radix);
void HostWriteBin(const byte *ID,int BitCnt,int DigitCnt);
void HostWriteDec(const byte *ID,int BitCnt,int DigitCnt);
void HostWriteHex(const byte *ID,int BitCnt,int DigitCnt);
void HostWriteVersion(void);

#endif

// ******************************************************************
// ****** ApplePay Helpers ******************************************
// ******************************************************************

void ApplePayApp_WaitRemoved(void);

// ******************************************************************
// ****** AppleVAS **************************************************
// ******************************************************************

bool AppleVAS_ReadCardData(byte *CardData,int *CardDataLen,int MaxCardDataLen);

// ******************************************************************
// ****** Transact **************************************************
// ******************************************************************

#define TRANSACTREADAPPLE           0x01
#define TRANSACTREADGPAY            0x02
#define TRANSACTREADDESFIRE         0x04
#define TRANSACTREADMIFARE          0x08

void Transact_SetReadTypes(int ReadTypes);
bool Transact_ReadCardData(const TTransactKeys *Keys,byte *CardData,int *CardDataLen,int MaxCardDataLen);

// ******************************************************************
// ****** KleverKey *************************************************
// ******************************************************************

void InitKleverKey(void);
bool SearchKleverKey(int *TagType,int *IDBitCount,byte *ID,int MaxIDBytes);

// ******************************************************************
// ****** Safetrust *************************************************
// ******************************************************************

void InitSafetrust(void);
bool SearchSafetrust(int *TagType,int *IDBitCount,byte *ID,int MaxIDBytes);

// ******************************************************************
// ****** Google SmartTap *******************************************
// ******************************************************************

bool ReadCardDataGoogleSmartTap(byte* PassID, int* PassIDByteCnt, int MaxPassIDByteCnt);

// ******************************************************************
// ****** Elatec Access *********************************************
// ******************************************************************

bool ElatecAccess_ReadCardData(byte *CardData, int *CardDataLen, int MaxCardDataLen);


// ******************************************************************
// ****** OSDP ******************************************************
// ******************************************************************

#define OSDP_CARD_DATA_BUFFER_SIZE 145      // Transponder ID cannot be longer than this many bytes
#define OSDP_KEYPAD_DATA_BUFFER_SIZE 116    // Keypad ID cannot be longer than this many bytes

/**
 * @brief Well, kinda survived the ages. Still there
 * @author Glep
 *
 * @return typedef struct
 */
typedef struct __attribute__((__packed__))
{
    uint8_t     Compliance_ContactStatus        , Num_ContactStatus     ;
    uint8_t     Compliance_OutputControl        , Num_OutputControl     ;
    uint8_t     Compliance_CardDataFormat       , Num_CardDataFormat    ;
    uint8_t     Compliance_LEDControl           , Num_LEDControl        ;
    uint8_t     Compliance_AudibleOutput        , Num_AudibleOutput     ;
    uint8_t     Compliance_TextOutput           , Num_TextOutput        ;
    uint8_t     Compliance_TimeKeeping          , Num_TimeKeeping       ;
    uint8_t     Compliance_CheckCharSupport     , Num_CheckCharSupport  ;
    uint8_t     Compliance_ComSecurity          , Num_ComSecurity       ;
    uint8_t     Compliance_SmartCardSupport     , Num_SmartCardSupport  ;
    uint8_t     Compliance_Readers              , Num_Readers           ;
    uint8_t     Compliance_Biometrics           , Num_Biometrics        ;
    uint8_t     Compliance_SecurePINEntry       , Num_SecurePINEntry    ;
    uint8_t     Compliance_OSDPVersion          , Num_OSDPVersion       ;
} TOSDPCapabilities;

/*
 * @brief   Represents the key management options you have to connect to the reader
 * @note    Only one can be configured -- choose wisely!
 *
 */
typedef enum _TKeyOption
{
    KEY_OPTION_NONE,                        // Security disabled -- No OSDP message encryption enabled
    KEY_OPTION_FIXED,                       // Default option for the SCBK - there is a preconfigured key and this one is used. No default key is allowed
    KEY_OPTION_FIXED_DEFAULT,               // there is a preconfigured key which is used. It is also possible to connect via the default handshake method with SCBK_D
    KEY_OPTION_FIXED_INSTALLATIONMODE,      // It is possible to connect to the reader with a preconfigured key and by using the default key and then set a new SCBK as often you want
    KEY_OPTION_FIXED_INSTALLATIONMODE_ONCE, // It is possible to connect to the reader with a preconfigured key and by using the default key and then set a new SCBK but only once (be careful!)
    KEY_OPTION_INDIVIDUAL,                  // This way the SCBK is calculated by the method described in the OSDP specification-Security Apendix B. Each reader then holds a individual key
    __KEY_OPTION_COUNT_ENUM
} TKeyOption;

/**
 * @brief     Defines the types of dirrerentiation between two color mapping modes via
 *            OSDP. ID-Dominant or Color-Dominant.
 *            ID-Dominant: The ID decides which LED is meant (standard)
 *            Color-Dominant:    Each LED is monochrom. Color Red will always switch on
 *                               the red LED, no matter what ID is sent via OSDP message
 */
typedef enum _TOSDPLEDAddressMode
{
    OSDP_LED_ADDRESS_MODE_ID = 0,
    OSDP_LED_ADDRESS_MODE_COLOR = 1
} TOSDPLEDAddressMode;

/**
 * @brief Represents available color options for led configuration
 *
 */
typedef enum
{
  OSDP_COLOR_OPTION_BLACK   = 0,
  OSDP_COLOR_OPTION_RED     = 1,
  OSDP_COLOR_OPTION_GREEN   = 2,
  OSDP_COLOR_OPTION_AMBER   = 3,
  OSDP_COLOR_OPTION_BLUE    = 4,
  OSDP_COLOR_OPTION_MAGENTA = 5,
  OSDP_COLOR_OPTION_CYAN    = 6,
  OSDP_COLOR_OPTION_WHITE   = 7,
  OSDP_COLOR_OPTION_RGB     = 8
} TOSDPColorOption;

/**
 * @brief Describes all possible OSDP colors (not all necessarely supported)
 *
 */
typedef enum _TOSDPLedColor
{
    OSDP_LED_COLOR_BLACK    = 0,
    OSDP_LED_COLOR_RED      = 1,
    OSDP_LED_COLOR_GREEN    = 2,
    OSDP_LED_COLOR_AMBER    = 3,
    OSDP_LED_COLOR_BLUE     = 4,
    OSDP_LED_COLOR_MAGENTA  = 5,
    OSDP_LED_COLOR_CYAN     = 6,
    OSDP_LED_COLOR_WHITE    = 7
} TOSDPLedColor;

/**
 * @brief This holds the LED mapping informations coming from AppBlaster
 *
 */
typedef struct __attribute__((__packed__)) _OSDPLEDMapping
{
    byte Color;
    int PhysicalLEDMask;
} TOSDPLEDMapping;

/**
 * @brief Available Tamper Modes for reader
 *
 */
typedef enum __attribute__((__packed__)) _TTamperMode
{
    TAMPER_MODE_OFF         = 0,
    TAMPER_MODE_NORMAL      = 1,
    TAMPER_MODE_INVERTED    = 2
} TTamperMode;

/**
 * @brief   Special value in case address is read from DIP switch
 * @note    If it is not possible to read address from DIP switch
 *          the app will use the default address of 0
 * @note    If there is a address found in memory, the app will
 *          always ignore the DIP address
 *
 */
#define OSDP_ADDRESS_DIP -1

/**
 * @brief   Special value in case baud rate is read from DIP switch
 * @note    If it is not possible to read baudrate from DIP switch
 *          the app will use the default baudrate 9600
 * @note    If there is a address found in memory, the app will
 *          always ignore the DIP baudrate
 */
#define OSDP_BAUDRATE_DIP -1


/**
 * @brief   Available Bias options
 * @note    Fallback option is always false
 *
 */
typedef enum _TOSDPBias
{
    OSDP_BIAS_DIP = -1,
    OSDP_BIAS_OFF =  0,
    OSDP_BIAS_ON  =  1,
} TOSDPBias;

typedef struct __attribute__((__packed__)) _TOSDPCardData
{
    int TagType;                                // This variable holds the TagType of the "SearchTag" function, it is not really used actively -- it is not really used by the OSDP driver, just backs it up for debugging purposes
    int IDBitCnt;                               // This variable holds the !BIT!count of the ID coming from "SearchTag" -- it is not really used by the OSDP driver, just backs it up for debugging purposes
    byte ID[OSDP_CARD_DATA_BUFFER_SIZE];        // This array holds the ID coming from "SearchTag" -- it is not really used by the OSDP driver, just backs it up for debugging purposes
    int RawBitCnt;                              // The count of the !BITS! -- only interesting if type RAW is selected
    byte RawBits[OSDP_CARD_DATA_BUFFER_SIZE];   // This arrry holds the !BITS! (not bytes) each index stands for a single bit -- only interesting if type RAW is selected
    // Additional byte for null termination (which is not transmitted to the host)
    char FormattedString[OSDP_CARD_DATA_BUFFER_SIZE+1]; // If FMT is used, the ReadCardData-function stores here the 0-Terminated ASCII string. ReadCardData is normally coming from the AppBlaster
} TOSDPCardData;

typedef struct __attribute__((__packed__)) _TOSDPKeypadData
{
    byte Number_Length;
    byte Number[OSDP_KEYPAD_DATA_BUFFER_SIZE];
} TOSDPKeypadData;

/// @brief Represents available options for reporting Keyboard Data entered by user
typedef enum _TKeyboardReportOptions
{
    KEYBOARD_REPORTOPTION_KEYBOARDCOMMAND,     // Entered Keyboard Numbers will be cached and sent out after the key '#' is pressed by the next
                                                // Poll request from master (via OSDP_KEYPAD)
    KEYBOARD_REPORTOPTION_RAW,       // Entered Keyboard Numbers will be cached and sent out after the key '#' is pressed
    KEYBOARD_REPORTOPTION_FMT
}TKeyboardReportOptions;

typedef enum _TKeyboardLightTriggers
{
    KEYBOARD_LIGHTTRIGGERS_OFF = 0x00,
    KEYBOARD_LIGHTTRIGGER_PROX = 0x01,
    KEYBOARD_LIGHTTRIGGER_TAG =  0x02,
    KEYBOARD_LIGHTTRIGGER_KEY =  0x04
} TKeyboardLightTriggers;

typedef enum _TOSDPSearchOptions
{
    SEARCH_OPTION_PERMANENT,
    SEARCH_OPTION_PROXTRIGGERED
}TOSDPSearchOptions;

/**
 * @brief Available Keyboard Modes for reader
 * @param KEYBOARD_MODE_OFF     Keyboard is disabled
 * @param KEYBOARD_MODE_NORMAL  Keyboard is enabled -- Further options are available via @TKeyboardReportOptions
*/
typedef enum _TKeyboardModes
{
    KEYBOARD_MODE_OFF,              // Nothing to be said here, not keypad -- this also is the fallback mode for other hardware
    KEYBOARD_MODE_NORMAL,           // Normal behaviour of keypad, the keypad is polled all the time - will send out the data via Keypad-command or RAW or FMT see @TKeyboardReportOptions
} TKeyboardModes;

/**
 * @brief Available Auto Encryption Modes for reader
 * @param AUTO_ENCRYPTION_MODE_OFF     Auto encryption is disabled
 * @param AUTO_ENCRYPTION_MODE_ON      Auto encryption is enabled - it will send a not CARD DATA and no PIN DATA if the communication is not encrypted
 */
typedef enum __attribute__((__packed__)) _TAutoEncryptionMode
{
    AUTO_ENCRYPTION_MODE_OFF        = 0,
    AUTO_ENCRYPTION_MODE_ON         = 1
} TAutoEncryptionMode;


typedef enum {
    TLV_TYPE_UNKNOWN                    = 0,
    TLV_TYPE_ADDRESS                    = 1,
    TLV_TYPE_BAUDRATE                   = 2,
    TLV_TYPE_BIAS                       = 3,
    TLV_TYPE_TAMPERMODE                 = 4,
    TLV_TYPE_BUZZERFREQUENCY            = 5,
    TLV_TYPE_BUZZERVOLUME               = 6,
    TLV_TYPE_TERMINATION                = 7,
    TLV_TYPE_BRIGHTSENSITIVITY          = 8,
    TLV_TYPE_MINENVBRIGHTNESS           = 9,
    TLV_TYPE_MAXENVBRIGHTNESS           = 10,
    TLV_TYPE_KEYBOARDONTIME             = 11,
    TLV_TYPE_PROXLIMIT                  = 12,
    TLV_TYPE_KEYBOARDBRIGHTNESSCONTROL  = 13,
    TLV_TYPE_KEYBOARDLIGHTTRIGGERS      = 14,
    TLV_TYPE_SEARCHOPTION               = 15,
    TLV_TYPE_KEYBOARDMODE               = 16,
    TLV_TYPE_HCETIMEOUT                 = 17,
    _TLV_TYPE_NUM,
} TTLVTypes;

// Specify lengths of according types
#define TLV_LENGTH_ADDRESS                          1
#define TLV_LENGTH_BAUDRATE                         4
#define TLV_LENGTH_BIAS                             1
#define TLV_LENGTH_TAMPERMODE                       1
#define TLV_LENGTH_BUZZERFREQUENCY                  4
#define TLV_LENGTH_BUZZERVOLUME                     1
#define TLV_LENGTH_TERMINATION                      1
#define TLV_LENGTH_BRIGHTSENSITIVITY                1
#define TLV_LENGTH_MINENVBRIGHTNESS                 1
#define TLV_LENGTH_MAXENVBRIGHTNESS                 1
#define TLV_LENGTH_KEYBOARDONTIME                   4
#define TLV_LENGTH_PROXLIMIT                        1
#define TLV_LENGTH_KEYBOARDBRIGHTNESSCONTROL        1
#define TLV_LENGTH_KEYBOARDLIGHTTRIGGERS            1
#define TLV_LENGTH_SEARCHOPTION                     1
#define TLV_LENGTH_KEYBOARDMODE                     1
#define TLV_LENGTH_HCETIMEOUT                       4

typedef struct _TOSDPParameter
{
    int Address;
    int Baudrate;
    TOSDPBias Bias;                                 // Selected Bias Mode
    TTamperMode TamperMode;                         // Selected Tamper Mode
    int BuzzerFrequency;
    int BuzzerVolume;                               // 0..100
    bool Termination;
    byte BrightSensitivity;                         // 0..100
    int MinEnvBrightness;                           // 0..100, Determines the minimal brightness the keys should have (can also be bigger than MaxEnvBrightness; behaviour will then be inverted)
    int MaxEnvBrightness;                           // 0..100, Determines the minimal brightness the keys should have (can also be smaller than MinEnvBrightness; behaviour will then be inverted)
    int KeyboardOnTime;                             // Sets the time in ms how long the keyboard will stay on when light events are triggered
    int ProxLimit;                                  // 10..100, Min reflection value reported from Proximity Sensor which will trigger the the Prox Alarm Event
    bool KeyboardBrightnessControl;                 // By switching this on and off, you can control if the Keyboard will try to compensate the environment brightness
    TKeyboardLightTriggers KeyboardLightTriggers;   // Light Events which will trigger the keyboard lights to start. The options can be combined by "or"-Operations with available Options in enum @TKeyboardLightTrigger
    TOSDPSearchOptions SearchOption;                // This field defines if transponder are searched permanently
    TKeyboardModes KeyboardMode;                    // This field defines if the keyboard mode is "Normal" or "Off"--Currently there are no other modes available
    uint32_t HCETimeout;                            // TODO: This is not yet implemented
    uint32_t SmartConfigTime;                       // Smart configuration: Time in seconds after powercycle, where smart configuration is possible. 0 -> turned off. UINT32_MAX -> always turned on
    bool SmartConfigNeedTamper;                     // Smart configuration: true -> tampering needed; false -> no tampering needed
} TOSDPParameter;

/**
 * Defines the max number of TTLV Objects in an TTLVChain
*/
#define MAX_NUMBER_TLV_OBJECTS  50

/**
 * Defines the max number of bytes contained in the data field of TTLV objects
*/
#define MAX_TLV_OBJECT_SIZE     50

// A structure to represent a TLV object.
// --------------------------------------
// Only use for legacy reasons
typedef struct __attribute__((__packed__)) _TTLV
{
    byte Type;
    byte Size;
    byte Data[MAX_TLV_OBJECT_SIZE];
}TTLV;

typedef enum 
{
    OSDP_IO_GPIO0   = 0x0001,
    OSDP_IO_GPIO1   = 0x0002,
    OSDP_IO_GPIO2   = 0x0004,
    OSDP_IO_GPIO3   = 0x0008,
    OSDP_IO_GPIO4   = 0x0010,
    OSDP_IO_GPIO5   = 0x0020,
    OSDP_IO_GPIO6   = 0x0040,
    OSDP_IO_GPIO7   = 0x0080,
    OSDP_IO_IN1     = 0x0100,
    OSDP_IO_IN2     = 0x0200,
    OSDP_IO_IN3     = 0x0400,
}TOSDPIOPins;

typedef enum
{
    OSDP_IOOTYPE_PUSHPULL       = 0,
    OSDP_IOOTYPE_OPENDRAIN      = 1
}TOSDPIOOTypes;

typedef enum
{
    OSDP_IOPUPD_NOPULL          = 0,
    OSDP_IOPUPD_PULLUP          = 1,
    OSDP_IOPUPD_PULLDOWN        = 2
}TOSDPIOPUpD;

typedef enum
{
    OSDP_IOTYPE_IN      = 0,
    OSDP_IOTYPE_OUT     = 1
}TOSDPIOTypes;

typedef struct
{
    TOSDPIOPins     Pin;
    TOSDPIOTypes    Type;
    TOSDPIOOTypes   OType;
    TOSDPIOPUpD     PUpDown;
}TOSDPIO;

typedef struct 
{
    int         Pin;
    TOSDPIOPUpD PUpDown;
} TOSDPInput;

typedef struct
{
    int Pin;
    TOSDPIOOTypes   OType;
    TOSDPIOPUpD     PUpDown;
} TOSDPOutput;


/**
 * @brief Holds all necessary informations for OSDP App
 *
 */
typedef struct _OSDPConfig
{
    TOSDPParameter Parameters;
    // More parameters todo:
    uint32_t ConnectionTimeout;                  // Holds the max time the reader will stay in connected state, when no new valid message is received with this PDs address
    int CardTimeout;                             // How long to wait after each card starting when the previous card has left the field
    TKeyboardReportOptions KeyboardReportOption; // This configures the way Keypad Data is reported via OSDP --> see @TKeyboardReportOptions

    byte ProjectID[4]; // Project ID - ID in which project this reader is grouped
    byte GroupID[4];   // Group ID - ID in which this reader is grouped

    byte SCBK[16];        // Key for OSDP Encryption
    byte SCBK_D[16];      // Default Key for OSDP Encryption - dependent on KeyOption
    byte MasterKey[16];   // Master Key for Diversified Key generation - dependent on KeyOption
    TKeyOption KeyOption; // Which key management is choosed @KeyOptions
                          // KEY_OPTION_NONE (security off)
                          // KEY_OPTION_FIXED
                          // KEY_OPTION_FIXED_DEFAULT
                          // KEY_OPTION_FIXED_INSTALLATIONMODE
                          // KEY_OPTION_FIXED_INSTALLATIONMODE_ONCE
                          // KEY_OPTION_INDIVIDUAL

    TAutoEncryptionMode AutoEncryptionMode; // Which key management is choosed @KeyOptions
                                            // AUTO_ENCRYPTION_MODE_OFF
                                            // AUTO_ENCRYPTION_MODE_ON


    bool FMT; // Which message will be prompted, when a transpnder is found RAW/FMT

    bool NAKWhiteListed;    // if true, this command/respond will be sent/handled unencrypted even in a encrypted session
    bool IDWhiteListed;     // if true, this command/respond will be sent/handled unencrypted even in a encrypted session
    bool CAPWhiteListed;    // if true, this command/respond will be sent/handled unencrypted even in a encrypted session
    bool COMSETWhiteListed; // if true, this command/respond will be sent/handled unencrypted even in a encrypted session

    TOSDPCapabilities Cap; // Capabilies from current reader

    const TOSDPLEDMapping *pLEDMapping;     // Holds the user configuration for reader LEDs
    TOSDPLEDAddressMode LEDMode;

    const TOSDPInput *Inputs;               
    const TOSDPOutput *Outputs;

    TOSDPInput TamperInput;
    
    int ComChannel;                         // Holds the current communication channel for OSDP

    // Standard search function must be implemented by the app
    bool (*pAppSearchTag)(TOSDPCardData *Card);
    // Standard function for reading card data must be implemented by the app
    bool (*pReadCardData)(TOSDPCardData *Card);


    void (*pOnStartup)(void);         // Function Pointer to subroutine handling startup signaling
    void (*pOnRestart)(void);         // Function Pointer to subroutine handling signaling before restart
    void (*pOnCardInvalid)(void);     // Function Pointer to subroutine handling signaling
                                      // when a card was found to be INVALID (failed reading
                                      // data from the card)
    void (*pOnCardValid)(void);       // Function Pointer to subroutine handling signaling
                                      // when a card was found to be VALID (data was read
                                      // from card successfully)
    void (*pOnCardTimeout)(void);     // Function Pointer to subroutine handling signaling
                                      // when tag block times out
    void (*pOnOnline)(void);          // Function Pointer to subroutine handling signaling
                                      // when OSDP connection is online
    void (*pOnOffline)(void);         // Function Pointer to subroutine handling signaling
                                      // when OSDP connection times out with 8 sec
    void (*pOnTamperDetect)(void);    // Function Pointer to subroutine handling signaling
                                      // an tamper alarm
    void (*pOnFirmwareUpdate)(void);  // Function Pointer to subroutine handling signaling
                                      // a running firmware update.
    void (*pOnKeyPress)(void);        // Function Pointer to subroutine handling signaling
                                      // if user presses a keypad key (not enter key!)
    void (*pOnEnterKey)(void);        // Function Pointer to subroutine handling signaling
                                      // if user presses the enter key
    void (*pOnDeleteKey)(void);       // Function Pointer to subroutine handling signaling
                                      // if user presses the enter key
    void (*pOnLoad)(void);            // gets called after init of OSDPApp is done but BE-
                                      // FORE communication and threads are started
                                      // in contrast to pOnStartUp, which is called AFTER
                                      // the threads were started and signalling etc. takes
                                      // effect
    int (*pOnCustomTLV)(int Type,int Length,const byte *Value);        // gets called vor every custom TLV parameter received.
                                                                        // NOT FOR EVERY MESSAGE! This means, if one TLV-MFG-Command
                                                                        // is received, which contains of 5 TLV commands, it will
                                                                        // call this handler five times in a row for each TLV-value
    void (*pOnEnterSmartConfig)(void);// Function pointer to subroutine which signals entering
                                      // configuration with smart phone (aka "smart config")

} TOSDPConfig;

bool OSDPAppSetup(const TOSDPConfig *DefaultConfig);
void OSDPAppBackgroundTasks(void);
void OSDPAppForegroundTasks(void);
void OSDPAppTransponderTask(bool (*ReadCardData)(TOSDPCardData *CardData));
void TickTask(void);
void GPIOTickTask(void);
void IPETickTask(void);
void SecustosTickTask(void);
void IPEHighPrioTask(void);
void GPIOHighPrioTask(void);
void SecustosHighPrioTask(void);


bool OSDPLEDSet(int ID, TOSDPLedColor Color);
bool OSDPLEDBlink(int ID, TOSDPLedColor OnColor, TOSDPLedColor OffColor, int OnTime, int OffTime);

void OSDPBeep(int Count, int OnTime, int OffTime);
void OSDPBuzzerOff(void);

bool OSDPGetParameter(int Type, byte *Buffer, int MaxSize);
bool OSDPSetParameter(int Type, const byte *Buffer, int Length);

/**
 * @brief Holds Wavelynx mobile credential metadata
 *
 */
typedef struct __attribute__((__packed__))
{
	struct TWavelynxECPSettings
	{
		byte TCI[3];
		byte ecpFormat;
		byte ecpTerminalMode;
		byte ecpTerminalType;
		byte ecpTerminalSubType;
		byte ecpBitCount;
		byte ecpAppOptions;
	} ECPSettings;
	struct TWavelynxMF2GoSettings
	{
		byte AID[3];
		byte DFNameLength;
		byte DFName[16];
	} MF2GoSettings;
} TWavelynxCustomSettings;

bool WLiOSReadData(int cryptoEnvironment, TWavelynxCustomSettings* CustomSettings, byte* CardData, int CardDataMaxBytes, int* BytesCopied, int bytesToRead);
bool WLGetCustomSettings(TWavelynxCustomSettings* CustomSettings);
bool WLMF2GoReadData(int cryptoEnvironment, TWavelynxCustomSettings* CustomSettings, byte* CardData, int CardDataMaxBytes, int* BytesCopied, int bytesToRead);

#endif
