#ifndef _GPIB_PARSER_
#define _GPIB_PARSER_
//---------------------------------------------------------------------------
#include <string.h>    // uses strcmp(), strstr()
//#include <acmmem.h>    // uses strcmp(), strstr()

#include "gpib_parser_casts.h"
#include "gpib_parser_validators.h"

#include "gpib_parser_numutils.h"
#include "gpib_parser_strutils.h"

// ERROR_USBTMC_*
// Standard USBTMC error codes
#define ERROR_USBTMC_DATANOTFOUND               1
#define ERROR_USBTMC_NOTHERMCOMPDATA            2
#define ERROR_USBTMC_ARRAY_CORRUPTED            3
#define ERROR_USBTMC_TOOMANY_REQUESTS           4
#define ERROR_USBTMC_INTERNAL                   5
//#define ERROR_USBTMC_BUFFER_OVERFLOW_OUT        6
//#define ERROR_USBTMC_BUFFER_OVERFLOW_IN         7  
// #define ERROR_USBTMC_HEADER_CORRUPTED           8
#define ERROR_USBTMC_COMMANDONLY                -110
#define ERROR_USBTMC_REQUESTONLY                -110
#define ERROR_USBTMC_INVALID_HEADER             -110
#define ERROR_USBTMC_EXECUTION                  -102
#define ERROR_USBTMC_PARAMETER                  -220
#define ERROR_USBTMC_TRIGGERIGNORED             -211

// The state machine: the ESR register bits
#define GPIB_ERROR_ID_COR      (0x80000000)  // Command or Request, (GPIB_ERROR_ID_COR|0x00000001) === Request
#define GPIB_ERROR_ID_EXE      (0x40000000)  // Execution Error

// Internal error codes:
#define ERROR_GPIB_INTERNAL            		 1
#define ERROR_GPIB_WRONG_PARAMETERS_COUNT 	 2
#define ERROR_GPIB_INVALID_PARAMETER   		 3
#define ERROR_GPIB_REQUEST_ONLY_SUPPORT		 4
#define ERROR_GPIB_INVALID_PARAMETER_TYPE	 5
// #define ERROR_GPIB_PARAMETER_NOT_SUPPORTED	 6  // not used
#define ERROR_GPIB_DATA_NOT_FOUND		 7                
#define ERROR_GPIB_COMMAND_ONLY_SUPPORT		 8
#define ERROR_GPIB_BUFFER_OVERFLOW		 9
#define ERROR_GPIB_ARRAY_CORRUPTED	 	 10
#define ERROR_GPIB_TOO_MANY_REQUESTS             11
#define ERROR_GPIB_THERMDATA_NOT_FOUND           12
#define ERROR_GPIB_UNCOMPLETE_COMMAND            13
#define ERROR_GPIB_TRIGGER_IGNORED               14
#define ERROR_GPIB_INVALID_ENUM_PARAMETERS       15 
//#define ERROR_GPIB_HEADER_CORRUPTED              16 

typedef unsigned int ( * TCmdParser_f)( USB_DEVICE_INFO *, QUEUE *, BOOL );

typedef enum 
{
    eParTypeNone,
    eParTypeNR1,           // SCPI Parameter type NR1, integer (positive, zero, negative), "-17", "2", "7", "0", "46"
    eParTypeNR2,           // SCPI Parameter type NR2, float (positive, zero, negative), "-17.0", "2.7", "0.46"
    eParTypeNR3,           // SCPI Parameter type NR3, scientific float (positive, zero, negative), "-1.70E+1", "+2.70E+0", "4.60E-1"
    eParTypeChar,          // SCPI Parameter type CHAR, ASCII character
    eParTypeString,        // SCPI Parameter type STRING, a wrapped with single or double quote sequence of CHAR's, must begin with a queue and must end with the same quote
    eParTypeDatablock      // SCPI Parameter type BLOCK, a large quantity of related data
} 
eParameterType_t;

// MEMORY_SIZE_PARAMQUEUE:
// The size in bytes of the queue for passing parameters
#define MEMORY_SIZE_PARAMQUEUE                               RAM_SCPIPARAM_SIZE

 #define GPIB_DUMMY_FUNCTION ( GPIB_Default_Handler )
 #define GPIB_DEF_FUNCTION ( GPIB_Default_Handler )


// ============================================================================================================
struct __sScpiCommand;
struct __sScpiCommand
{
  const char *                     header;         // a command mnemonic (name)
  const char *                     shortheader;    // a short command mnemonic
  BOOL                       enablerequest;  // the sign if the orignal name is equals to the user-typed name (excluding the last '?'-character)  
  TCmdParser_f               function;       // command parser function
  unsigned short int         childcount;     // amount of child commands
  unsigned short int         childcountmax;  // maximum available count of child commands
  struct __sScpiCommand *    pcommands;      // a list of child commands

  BOOL            bTagArgUsed;               // Use a special tag parameter to specialize the handler call
  unsigned int    xTagArg;                   // an extra tag parameter for the handler
  
};
typedef struct __sScpiCommand sScpiCommand_t;
// ============================================================================================================
unsigned int GPIB_Default_Handler(  USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL req );
unsigned int GPIB_SystemVersion( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL  req  );
unsigned int GPIB_Identification (  USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL req );
unsigned int GPIB_Reset( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_Clear( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_EventStatusEnable( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_EventStatusRegister( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_OperationComplete( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_Trigger( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_Wait( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_InterfaceSwitch( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_SystemError( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_SystemErrorAll( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusOperationEvent( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusOperationCondition( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusOperationEnable( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusQuestionableEvent( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusQuestionableCondition( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_StatusQuestionableEnable( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );  
unsigned int GPIB_StatusPreset( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_GetTemperature( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_SwitchCount( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_SwitchState( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_SwitchList( USB_DEVICE_INFO * udi, QUEUE * pQParametes, BOOL request );
unsigned int GPIB_MemTablePoints( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableTime( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableDate( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableTemp( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableFields( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableConn( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableAdap( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableAnalyzer( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTablePlace( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableOperator( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableData( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_MemTableTherFunction( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_StatusEnableRegister( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
unsigned int GPIB_StatusRegister( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );

eChrz_t GPIB_GetChrzTableId( const char * pParamText, size_t nTextLen );
ePortId_t GPIB_GetPortId( const char * pParamText, size_t nTextLen );
ePortComb_t GPIB_GetPortComb( const char * pParamText, size_t nTextLen );
ePortStateId_t GPIB_GetPortStateId( const char * pParamText, size_t nTextLen );

size_t GPIB_MemoryTablePoints( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableDate( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableTime( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableTemp( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableFreqType( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableFreqData( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableFreqSegmData( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableFreqStart( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableFreqStop( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableConnector( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableAdapter( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableAnalyzer( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTablePlace( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableOperator( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemoryTableData( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemTableTherCorrFreqStart( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemTableTherCorrFreqStop( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemTableTherCorrPoints( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemTableTherCorrPhase( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );
size_t GPIB_MemTableTherCorrMagniture( USB_DEVICE_INFO * udi, QUEUE * pQParameters, BOOL request );

// ============================================================================================================
void GPIB_DevDepInit( USB_DEVICE_INFO * udi );

// GPIB_EnumParameters:
// Processes the @pParamString with @length length and parses the command parameters.
// The following SCPI types are supported:
// - NR1, NR2, NR3
// - Mnemonic (character)
// - Strings
// - binary DataBlock
// All the parameters are packed into the @pQueue
// In case an error occurred, the function interrupts processing and return an error code.
// Note: in case of error the @pQueue is already modified.
// @pParamString - the source string
// @length - the length of @pParamString
// @pQueue - the queue to pack parameters in
// @pEnd - optional pointer to store the end of parsed string after parsing. Can be NULL. 
// If @pEnd isn't NULL, it will contain the pointer to the character after the lastest parsed character in @pParamString.
// Return: error code (negative) or number of parsed parameters (positive)
int GPIB_EnumParameters( const char * parstring, size_t strl, QUEUE * pQueue, const char ** pEnd );

int  GPIB_CommandExecute( USB_DEVICE_INFO * udi, const char * str );
sScpiCommand_t * GPIB_InitializeAllCommands( void );



unsigned int GPIB_RaiseStandartError( USB_DEVICE_INFO * udi, 
                                      unsigned int errCode, 
                                      const char * data, 
                                      GPIB_ErrorClass_t errClass
                                    );

//char * GPIB_GetStringEnd( char * gpibstr, unsigned int datalen );
//ESTATE GPIB_GetKeystateID( char * sQueueParameter, unsigned int dwQueueParameterSize, BOOL ExpandFormat );
//EPORT GPIB_GetPortID( char * sQueueParameter, unsigned int dwQueueParameterSize );
//char * GPIB_StrChr( char * str, char chr, char * end );
unsigned int GPIBInit( USB_DEVICE_INFO * udi );
#endif
 