#include "open62541.h"

#include <stdio.h>
#include <signal.h>

#include <stdlib.h>
#include <assert.h>

typedef unsigned char		u8;
typedef unsigned short		u16;
typedef unsigned int		u32;
typedef long long 			TIME;
typedef long long			DT;	
//typedef int                 bool;
#define bool _Bool
#define true                1
#define false               0
#define MAX_ELEMENTS_INDEXRANGE 	10
#define MAX_ELEMENTS_BROWSERESULT 	10
#define MAX_ELEMENTS_NODELIST		10
#define MAX_ELEMENTS_ARRAYDIMENSION	10
#define MAX_ELEMENTS_NAMESPACES 	10
#define MAX_ELEMENTS_RELATIVEPATH	10
#define MAX_ELEMENTS_MONITORLIST	10
#define MAX_ELEMENTS_SELECTIONS		10
#define MAX_ELEMENTS_EVENTITEMLIST	10
#define MAX_ELEMENTS_METHOD			10

typedef struct {
	int type;
	void *data;
} UA_Value;

typedef struct {
	int ArgumentSize;
	UA_Value *value;
} UA_Arguments;
/*PLCopen strand UA date type*/


typedef struct {
    size_t length; /* The length of the string */
    u8 *data; /* The content (not null-terminated) */
} STRING;

typedef enum {
    UASMM_BestAvailable    	= 0, 
    UASMM_None     			= 1,
    UASMM_Sign       		= 2,
    UASMM_SignEncrypt 		= 3
}UASecurityMsgMode;

typedef enum {
    UASP_BestAvailable    	= 0, 
    UASP_None     			= 1,
    UASP_Basic128Rsa15      = 2,
    UASP_Basic256 			= 3,
	UASP_Basic256Sha256		= 4
}UASecurityPolicy;

typedef enum {
    UATP_UATcp    			= 1, 
    UATP_WSHttpBinary     	= 2,
    UATP_WSHttpXmlOrBinary  = 3,
    UATP_WSHttpXml 			= 4
}UATransportProfile;

typedef enum {
    UAIT_Numeric    = 0, 
    UAIT_String     = 1,
    UAIT_GUID       = 2,
    UAIT_Opaque 	= 3
}UAIdentifierType;


typedef enum {
    UAUITT_Anonymous    = 0, 
    UAUITT_Username     = 1,
    UAUITT_x509       	= 2,
    UAUITT_IssuedToken 	= 3
}UAUserIdentityTokenType;


typedef enum {
    UAMS_Unknown    		= 0, 
    UAMS_ControllerSync     = 1,
    UAMS_FwSync       		= 2
}UAMonitoringSyncMode;

typedef enum {
    UADT_None    			= 0, 
    UADT_Absolute     		= 1,
    UADT_Percent       		= 2
}UADeadbandType;

typedef enum {
    UABD_Forward    		= 0, 
    UABD_Inverse     		= 1,
    UABD_Both       		= 2
}UABrowseDirection;

typedef enum {
    UACS_Connected    		= 0, 
    UACS_ConnectionError    = 1,
    UACS_Shutdown       	= 2
}UAConnectionStatus;

typedef enum {
    UASS_Running    		= 0, 
    UASS_Failed    			= 1,
    UASS_NoConfiguration    = 2,
	UASS_Suspended			=3,
	UASS_Shutdown			=4,
	UASS_Test				=5,
	UASS_CommunicationFault	=6,
	UASS_Unknown			=7
}UAServerState;

typedef enum {
    ReferenceType    		= 1, 
    IsForward     			= 2,
    NodeClass       		= 4,
	BrowseName				= 8,
	DisplayName				= 16
}UABrowseResultMask;

typedef enum {
    UAHAUpdateStatusCode_HistorianRaw    		= 0, 
    UAHAUpdateStatusCode_HistorianCalculated    = 1,
    UAHAUpdateStatusCode_HistorianInterpolated  = 2,
	UAHAUpdateStatusCode_Reserved	 			= 3,
	UAHAUpdateStatusCode_HistorianPartial		= 4,
	UAHAUpdateStatusCode_HistorianExtraData		= 8,
	UAHAUpdateStatusCode_HistorianMultiValue	= 16
}UAHAUpdateStatusCode;

typedef enum  {
    UANCM_None    		= 0, 
    UANCM_Object     	= 1,
    UANCM_Variable		= 2,
    UANCM_Method 		= 4,
	UANCM_ObjectType	= 8,
	UANCM_VariableType	= 16,
	UANCM_ReferenceType	= 32,
	UANCM_DataType 		= 64,
	UANCM_View			= 128,
	UANCM_All			= 0x7fffffff
}UANodeClassMask;

typedef enum {
	UAAI_NodeID 					= 1,
	UAAI_NodeClass					= 2,
	UAAI_BrowseName					= 3,
	UAAI_DisplayName				= 4,
	UAAI_Description				= 5,
	UAAI_WriteMask					= 6,
	UAAI_UserWriteMask				= 7,
	UAAI_IsAbstract					= 8,
	UAAI_Symmetric					= 9,
	UAAI_InverseName				= 10,
	UAAI_ContainsNoLoops			= 11,
	UAAI_EventNotifier				= 12,
	UAAI_Value						= 13,
	UAAI_DataType					= 14,
	UAAI_ValueRank					= 15,
	UAAI_ArrayDimensions			= 16,
	UAAI_AccessLevel				= 17,
	UAAI_UserAccessLevel			= 18,
	UAAI_MinimumSamplingInterval	= 19,
	UAAI_Historizing				= 20,
	UAAI_Executable					= 21,
	UAAI_UserExeNamespaceIndexcutable				= 22
}UAAttributeID;

typedef struct {
    UAUserIdentityTokenType UserIdentityTokenType;
	STRING TokenParam1;
	STRING TokenParam2;
} UAUserIdentityToken;


typedef struct {
    u16 NamespaceIndex;
	STRING Identifier;
	UAIdentifierType IdentifierType;
} UANodeID;

typedef struct {
    u32 ServerIndex;
	STRING NamespaceURI;
	UANodeID ID;
} UAExpandedNodeID;

typedef struct 
{
	char *Locale;
	STRING Text;
}UALocalizedText;

typedef struct 
{
	u16 StartIndex;
	u16 EndIndex;
}UAIndexRange;


typedef struct {
    UANodeID ReferenceTypeID;
	bool IsForward;
	UAExpandedNodeID NodeID;
	STRING BrowseName;
	UALocalizedText DisplayName;
	UANodeClassMask NodeClass;
	UAExpandedNodeID TypeDefinition;
} UAReferenceDescription;

typedef struct 
{
	UAAttributeID AttributeID;
	u16 IndexRangeCount;
	UAIndexRange IndexRange[MAX_ELEMENTS_INDEXRANGE];
}UANodeAdditionalInfo;

typedef struct 
{
	u16 NamespaceIndex;
	STRING Name;
}UAQualifiedName;

typedef struct 
{
	u16 AccessLevel;				//
	u32 ArrayDimension[MAX_ELEMENTS_ARRAYDIMENSION];			//	
	UAQualifiedName BrowseName;		//
	bool ContainsNoLoops;			//
	UANodeID DataType;				//
	UALocalizedText Description;	//
	UALocalizedText DisplayName;	//
	u16 EventNotifier;				//
	bool Executable;				//
	bool Historizing;				//
	STRING InverseName;				//
	bool IsAbstract;				//
	TIME MinimumSamplingInterval;	//
	UANodeClassMask NodeClass;   	//
	bool Symmetric;					//
	u16 UserAccessLevel;			//
	bool UserExecutable;			//
	u32 UserWriteMask;				//
	int ValueRank;					//
	u32 WriteMask;					//
}UANodeInformation;

typedef struct 
{
	UANodeID ReferenceTypeId;
	bool IsInverse;
	bool IncludeSubtypes;
	UAQualifiedName TargetName;
}UARelativePathElement;

typedef struct 
{
	u16 NoOfElements;
	UARelativePathElement *Elements;
}UARelativePath;

typedef struct 
{
	UANodeID StartingNode;
	UARelativePath RelativePath;
}UABrowsePath;


typedef struct{
	//STRING SessionName;
	//STRING ApplicationName;
	UASecurityMsgMode SecurityMsgMode;
	UASecurityPolicy SecurityPolicy;
	STRING CertificateStore;
	STRING ClientCertificateName;
	STRING ServerUri;
	bool CheckServerCertificate;
	//UATransportProfile TransportProfile;
	//UAUserIdentityToken UserIdentityToken;
	TIME SessionTimeout;
	//TIME MonitorConnection;
	//STRING LocaleIDs[6];
}UASessionConnectInfo;

typedef struct 
{
	UA_Value Values;
	DT TimeStamps;
	u32 *NodeQualityIDs;
	u16 NewValuesCount;
}UAMonitoredVariables;

typedef struct 
{
	TIME SamplingInterval;
	u16 QueueSize;
	bool DiscardOldest;
	UADeadbandType DeadbandType;
	float Deadband;
}UAMonitoringParameter;

typedef struct 
{
	UANodeID StartingNodeID;
	UABrowseDirection Direction;
	UANodeID ReferenceTypeID;
	bool IncludeSubtypes;
	UANodeClassMask NodeClass;
	UABrowseResultMask ResultMask;
}UABrowseDescription;

typedef struct 
{
	UA_Value Values;
	UAHAUpdateStatusCode StatusCode;
	TIME ServerTimeStamp;
	TIME SourceTimeStamp;
}UAHADataValue;

typedef struct 
{
    u16 nanoSec;
    u16 microSec;
    u16 milliSec;
    u16 sec;
    u16 min;
    u16 hour;
    u16 day;   /* From 1 to 31 */
    u16 month; /* From 1 to 12 */
    u16 year;
} UADateTimeStruct;

typedef struct 
{
    u16 Severity;
    STRING Message;
    STRING SourceName;
    UANodeID SourceNode;
    UANodeID EventType;
	TIME Time;
	TIME ReceiveTime;
}UAEventField;

/**
 * UA_Connect
 * ^^^^^^^^^^^
 */
u32 UA_Connect(STRING endpointUrl,UASessionConnectInfo SessionConnectInfo,long *ConnectionHdl);
/**
 * UA_Disconnect
 * ^^^^^^^^^^^
 */
u32 UA_Disconnect(long ConnectionHdl);

/**
 * UA_NamespaceGetIndexList
 * ^^^^^^^^^^^
 */
u32 UA_NamespaceGetIndexList(long ConnectionHdl,u16 NamespaceUrisCount,STRING *NamespaceUris,u16 *NamespaceIndexes);

/**
 * UA_ServerGetUriByIndex
 * ^^^^^^^^^^^
 */

u32 UA_ServerGetUriByIndex(long ConnectionHdl,u32 ServerIndex,STRING *ServerUri);
/**
 * UA_ServerGetIndexByUriList
 * ^^^^^^^^^^^
 */
u32 UA_ServerGetIndexByUriList(long ConnectionHdl,u16 ServerUrisCount,STRING ServerUris[],u16 *ServerIndexes);
/**
 * UA_TranslatePathList
 * ^^^^^^^^^^^
 */
u32 UA_TranslatePathList(long ConnectionHdl,u16 BrowsePathsCount,UABrowsePath BrowsePaths[],UANodeID *TargetNodeIDs);
/**
 * UA_NodeGetHandleList
 * ^^^^^^^^^^^
 */
u32 UA_NodeGetHandleList(long ConnectionHdl,u16 NodeIDCount,UANodeID *NodeIDs,long *NodeHdls,u32 ErrorIDs[]);
/**
 * UA_NodeReleaseHandleList
 * ^^^^^^^^^^^
 */
u32 UA_NodeReleaseHandleList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,u32 ErrorIDs[]);
/**
 * UA_NodeGetInformation
 * ^^^^^^^^^^^
 */
u32 UA_NodeGetInformation(long ConnectionHdl,UANodeID NodeID,UANodeInformation *NodeInfo,u32 ErrorIDs[]);
/**
 * UA_SubscriptionCreate
 * ^^^^^^^^^^^
 */
u32 UA_SubscriptionCreate(long ConnectionHdl,bool PublishingEnable,u16 Priority,long *SubscriptionHdl,TIME *PublishingInterval);
/**
 * UA_SubscriptionDelete
 * ^^^^^^^^^^^
 */
u32 UA_SubscriptionDelete(long ConnectionHdl,long SubscriptionHdl);

/**
 * UA_SubscriptionModify
 * ^^^^^^^^^^^
 */
u32 UA_SubscriptionModify(long ConnectionHdl,long SubscriptionHdl,bool PublishingEnable,u16 Priority,TIME *PublishingInterval);
/**
 * UA_SubscriptionProcessed
 * ^^^^^^^^^^^
 */
u32 UA_SubscriptionProcessed(long SubscriptionHdl);
/**
 * UA_MonitoredItemAddList
 * ^^^^^^^^^^^
 */
u32 UA_MonitoredItemAddList(long ConnectionHdl,long SubscriptionHdl,u16 NodeHdlCount,
                                                long *NodeHdls,UAMonitoringSyncMode SyncMode,
                                                UANodeAdditionalInfo *NodeAddInfos,u32 *MonitoredItemHdls,u32 ErrorIDs[]);
/**
 * UA_MonitoredItemRemoveList
 * ^^^^^^^^^^^
 */
u32 UA_MonitoredItemRemoveList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,long *MonitoredItemHdls,u32 ErrorIDs[]);
/**
 * UA_MonitoredItemModifyList
 * ^^^^^^^^^^^
 */
u32 UA_MonitoredItemModifyList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,
								long *MonitoredItemHdls,UAMonitoringParameter MonitoringParameter[],
								u32 ErrorIDs[]);
/**
 * UA_MonitoredItemOperateList
 * ^^^^^^^^^^^
 */
u32 UA_MonitoredItemOperateList(long ConnectionHdl,long SubscriptionHdl,u16 MonitoredItemHdlCount,long *MonitoredItemHdls,
								UAMonitoredVariables *Variables,
								bool *ValuesChanged,u16 *MinLostValueCount,u32 *NodeErrorIDs);
/**
 * UA_ReadList
 * ^^^^^^^^^^^
 */
u32 UA_ReadList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,UA_Value *variables,u32 ErrorIDs[]);
/**
 * UA_WriteList
 * ^^^^^^^^^^^
 */
u32 UA_WriteList(long ConnectionHdl,u16 NodeHdlCount,long *NodeHdls,UANodeAdditionalInfo *NodeAddInfos,UA_Value *variables,u32 ErrorIDs[]);
/**
 * UA_MethodGetHandleList
 * ^^^^^^^^^^^
 */
u32 UA_MethodGetHandleList(long ConnectionHdl,u16 NodeIDCount,UANodeID *ObjectNodeIDs,UANodeID *MethodNodeIDs,long *MethodHdls,u32 ErrorIDs[]);
/**
 * UA_MethodReleaseHandleList
 * ^^^^^^^^^^^
 */
u32 UA_MethodReleaseHandleList(long ConnectionHdl,u16 MethodHdlCount,long *MethodHdls,u32 *ErrorIDs);
/**
 * UA_MethodCall
 * ^^^^^^^^^^^
 */
u32 UA_MethodCall(long ConnectionHdl,long MethodHdl,UA_Arguments *InputArguments, UA_Arguments *OutputArguments);

/**
 * UA_Browse
 * ^^^^^^^^^^^
 */
u32 UA_Browse(long ConnectionHdl,UABrowseDescription BrowseDescription,u32 ContinuationPointIn,u16 *BrowseResultCount,UAReferenceDescription *BrowseResult,u32 ContinuationPointOut);

/**
 * UA_EventItemAdd
 * ^^^^^^^^^^^
 */
u32 UA_EventItemAdd(long ConnectionHdl,long SubscriptionHdl,long NodeHdl,
					UANodeID EventType,u16 EventFieldSelectionCount,
					UARelativePath *EventFieldSelections,long *EventItemHdl);

/**
 * UA_EventItemOperateList
 * ^^^^^^^^^^^
 */
u32 UA_EventItemOperateList(long ConnectionHdl,long SubscriptionHdl,u16 EventItemHdlCount,long *EventItemHdls,
							UAEventField *Fields,bool EventProcessed,
							u16 *RemainingEventCount,u32 *FieldErrorIDs);

/**
 * UA_EventItemRemoveList
 * ^^^^^^^^^^^
 */
u32 UA_EventItemRemoveList(long ConnectionHdl,long SubscriptionHdl,u16 EventItemHdlCount,long EventItemHdls,u32 ErrorIDs[]);

/**
 * UA_HistoryUpdate
 * ^^^^^^^^^^^
 */
u32 UA_HistoryUpdate(long ConnectionHdl,long NodeHdl,bool PerformInsert,bool PerformReplace,u16 DataValueCount,UAHADataValue *DataValues);

/**
 * UA_ConnectionGetStatus
 * ^^^^^^^^^^^
 */
u32 UA_ConnectionGetStatus(long ConnectionHdl,UAConnectionStatus *ConnectionStatus,UAServerState *ServerState,u8 *ServiceLevel);



// unsigned short UA_CreatClient(long *client);
// unsigned int UA_ConnectServer(long client, const char *endpointUrl);
// unsigned int UA_Client_writeValue(long client, char *NodeName, void *value, int type);
// unsigned int UA_Client_readNode(long client, char *NodeName, UA_Value *outValue);
// unsigned int UA_printValue(UA_Value *value);
// unsigned int UA_Client_HistoryRead(long client, char *NodeName);
// void UA_Client_Delete(long client);
// void UA_Value_Clear(UA_Value *p);
// void UA_Value_init(UA_Value *p);
// void Browse(long client);
