#ifndef __ND_PROXY_SERVER_H__
#define __ND_PROXY_SERVER_H__

/* This structure is the global structure of Proxy Server
 * It keeps all the necessary information to set-up
 * and initialize proxy server.
 */

#include <apr_poll.h>
#include "apr_thread_proc.h"
 //#include "../ndlb_mt_log.h"
#include "../NDCommonHeader.h"
#include "../NDMain.h"
#include "../agent_thread.h"
#include "../Server.h"
#include "../NDSys.h"
#include "apr_thread_cond.h"

#define NOCLEAN 0
#define CLEAN 1
struct callback_util {
    int size;
    char buf_to_send[LWS_PRE + 128 * BUFFER_LEN];
    int recv_size;
    int recv_max_size;
    char* recv_buf;
};
struct data_util_t {
    int size;
    char buf_to_send[LWS_PRE + 128 * BUFFER_LEN];
};
typedef struct
{
    char proxyServerFlag;		// Flag to support Standalone mode.
    char proxyConType;		// 0 - INET, 1 - Unix Domain Sockets.
    char* ndProxyUnixDomainPath;	// Unix domain socket path
    char* ndHomePath;
    char* ndcHost;
    char* proxyHost;
    char* tierName;
    char* appName;
    char* serverName;
    unsigned int proxyPort;
    unsigned int ndcPort;
    time_t udpTimeout;
    int num_udpThreads;
    int maxUDPProcesses;
    int maxTCPProcesses;
    unsigned int numInstances;	// Counter for num of instances connected to ProxyServer.
    unsigned int numUdpInstances;
    unsigned int numTcpUdpInstances;
    int sktFd;

    int total_process_entries;

    apr_pool_t* proxy_pool;	// Main pool 
    apr_socket_t* skt;		// Socket to open for listener on  Proxy.
    apr_socket_t* udp_skt;
    apr_hash_t* udp_client_timeout;
    //char *nvCookie;
    int enableNDSession;
    int shutdownProxy;
    //apr_thread_mutex_t *udpClientMapLock;
    lws_handler_t lws_handler;

    apr_pollset_t* pollset;
    const apr_pollfd_t* ret_pfd;
    const apr_pollfd_t* pfd;
    processInfoStruct_t *processInfoStruct;
    apr_thread_mutex_t *udp_connection_lock;
    rudp_packet_wrapper* udp_writeList;
    rudp_packet_wrapper* udp_writeListLast;
    apr_thread_mutex_t* udp_bufferWriteLock;
}NDProxy_t;

extern NDProxy_t NDProxy;

typedef struct
{
    int appIndex;
    int processIndex;
}PxAppEpollInfo_t;

extern PxAppEpollInfo_t pxAppEpoll;

typedef struct
{
    int appIndex;
}PxNDCEpollInfo_t;

extern PxNDCEpollInfo_t pxNDCEpoll;

typedef struct
{
    int data_len;
    int ctrlFd;
    int dcFd;
    int asFd;
    //int aiFd;
    int disFd;
    long long int processId;
    char* data;
    apr_socket_t* ctrlSocket;
    apr_socket_t* dcSocket;
    apr_socket_t* asSocket;
   // apr_socket_t *aiSocket;
    apr_socket_t *disSocket;
    //HPLOG:changes for websocket
    proxy_lws_handler_t ctrlLwsHandler;
    proxy_lws_handler_t dcLwsHandler;
    proxy_lws_handler_t asLwsHandler;
  //  proxy_lws_handler_t aiLwsHandler;
    proxy_lws_handler_t disLwsHandler;
    //HPEND
    PxAppEpollInfo_t *pxAppEpoll;		// Epoll structure to map the process and instance id
}instanceProcess_t;


typedef struct autoInstrumentationStruct_t
{
  char autoDeInstrFlg;
  char isInBlackListFlg;
  char ICRFlag;
  char *className;
  char *methodName;
  int count;
  long duration;
  long int addedTimeStamp;
  float avgTimeTaken;
}autoInstrumentationStruct_t;






typedef struct NDProxyInstance_t
{
    //char isAgentLess;
    char* agentName;
    char* tierName;
    char* appServerName;
    char* appName;
    //char* bciVersion;
    //char* ndHome;
    char* agentType;
    //char* serverIp;
    //char* hostName;
    //char* jvmType;
    //char* javaVersion;
    //char* javaHome;
    //char* machineType;
    //char* connDestination;
    //char* NDCollectorIP;
    char* startInstMsg;
    apr_hash_t* start_instr_map;
    apr_thread_mutex_t* start_instr_lock;
    char* tierAttr;
    char* tags;
    char* attributes;
    char* funcName;
    char *lambdaKey;
    int tierID;
    int serverID;
    int appID;
    //int NDCollectorPort;
    //int testIdx;
    //int requestType;
    int processCount;			// Total number of process request. Also used as index in accessing instance. 
    int activeProcessCount;		// Total number of connected process(active) for a particular instance

    instanceProcess_t* processInfo;	// This structure will hold the data for every process of NDAgent Application
    int close_udp_thread;
    //long long int lastConnectionTimeStamp;
    //long long int connDuration;
    //long long int bciStartTime;
    //long long int BCITimeStamp;
    long long int resetTimeInterval;  // This is for calling reset after a given time of interval.  
    long long int totalElapsedTime; // for calculation duration 

    Server_t Server;
    NDBCISetting_t NDBCISetting;
    NDSys_t NDSys;

    //apr_pollfd_t pfd;
    apr_hash_t* fpi_tls_map;
    apr_hash_t* udp_connections;


//    apr_socket_t* ndcCtrlSocket;
//    apr_socket_t* ndcDataSocket;
    //apr_socket_t* ndcASSocket;
    //HPLOG:Changes for websocekt
    //lws_handler_t ndcCtrlLwsHandler;
    //lws_handler_t ndcDataLwsHandler;
    //lws_handler_t ndcASLwsHandler;
    //HPEND
    socketInfo_t dataSkt;
    socketInfo_t autoSensor;


    nioSettings_t* NDCollectorBB;
    nioSettings_t* NDBCIAgentBB;

    nioSettings_t* writeList;
    nioSettings_t* writeListLast;
    nioSettings_t* readList;
    nioSettings_t* readListLast;
    int readListSize;
    int curBuffers; // Current number of buffers 
    apr_thread_t* data_thread_id;
    apr_pool_t* data_pool;


    /*AutoSensor Socket*/
    nioSettings_t* NDCollectorBBAS;
    nioSettings_t* NDBCIAgentBBAS;
    nioSettings_t* readListAS;
    nioSettings_t* readListLastAS;
    int readListSizeAS;
    int writeListSizeAS;
    int writeListSize;
    nioSettings_t* writeListAS;
    nioSettings_t* writeListLastAS;
    apr_thread_t* autoSensor_thread_id;
    apr_pool_t* autoSensor_pool;
    int maxBuffersAS;
    int dataBufferSizeAS;

    /*ndTD */
  /*  NDPerThreadData_t NDPerThreadData ;
    NDPerThreadData_t* gBusyTLSHead;
    NDPerThreadData_t* gBusyTLSTail;
    int gBusyTLSCnt;
    int gFreeTLSCnt;
    int g_tlsidx;
    NDPerThreadData_t* gFreeTLSHead;
    NDPerThreadData_t* gFreeTLSTail;
    TLSDataStruct* tlsdatastruct;
    //apr_thread_mutex_t *tlsMutex;*/             //Locally Removed

    apr_socket_t *AgentSocketInfo_skt;
    //AgentSocketInfo_t AgentSocketInfo;
    /*  apr_hash_t *ndTDHashMap;
      apr_thread_mutex_t *ndTDHashMapLock; */


    NDBTMonitor_t NDBTMonitor;
    //NDBackendManager_t NDBackendManager;
    NDBackendMonitor_t NDBackendMonitor;
    NDMethodMonitor_t NDMethodMonitor;


    ndHttpCapture_t ndHttpCapture;
    int httpid;
    node_t* httpHashMapNode;
    apr_thread_mutex_t* httpEntryLock;

    //controlSocketBuffer_t bufInfo;
    //controlSocketBuffer_t dataBufInfo;
    long long processID;

    int size_array;
    unsigned int server_arr_size;

    ASGraphData_t  asGraphData;

    ndAutoSensorUsingStackTrace_t ndAutoSensorUsingStackTrace;


    char retryFlagAS;
    char toStopASThread;

    apr_thread_mutex_t *methodEntryLock;
    node_t* methodHashMapNode;
    //node_t* methodHashMapNodeTemp;
    int methodIDGlobal; //Important //this is used as methodId counter for Entry Point Methods
    //int methodIDGlobal_inst; //this is used as methodId counter for InstrProf and Method Monitor Methods
    //apr_hash_t *threadBasedModelMap;
    NDSQLSetting_t NDSQLSetting;
    //NDThreadMonitor_t NDThreadMonitor;


    NDBTGlobalRule* global_rule;
    int bt_rule;
    NDBTManager manager;
    NDBTTagManager tagManager;
    NDBTConfigModel config;

    //PxNDCEpollInfo_t pxNDCEpoll;		// Epoll structure to map appid with NDC

    //char reportBuffer[MAX_REPORT_SIZE +1];
    char vectorPrefix_ID[ND_VECTOR_PREFIX_ID_SIZE + 1];
    char vectorPrefixHtsp[ND_VECTOR_PREFIX_SIZE + 1];

    socketInfo_t control; // Control Socke0t
    controlSocketBuffer_t ctrlBufInfo;
    int heartbeat_count;

    /*New added */
    char is_switch_over;
    ndc_servers_t *active_ndc;
    char nd_dr_state;
    //char health_check_fail;
    retryPolicy_t retry_policy;
    ndc_servers_t* ndc_server_arr;
    int isMasterNdc;

    NDDynamicSettings_t ndDynamicSettings;
    ndAutoInstrumentation_t ndAutoInstrumentation;
    //autoInstrumentation_t autoInstrumentation;
    int enable_DD_AI;
    char* DD_AI_Session_Name;

    apr_hash_t* exceptionMessageMap;
    apr_hash_t* exceptionCauseMap;
    apr_hash_t* exceptionThrowingMethodMap;
    apr_hash_t* exceptionThrowingClassMap;
    apr_hash_t* exceptionClassNameMap;

    //All Exception Structure Related Changes
    NDExceptionIDS_t ndExceptionIDS;
    NDException_t ndException;
    NDExceptionMonitor_t ndExceptionMonitor;
    NDExceptionMonitorDataCounters ndExceptionMonitorDataCounters;


    long long resourceMetaID;
    NDEnableResource_t getenableResource;
    apr_hash_t* resourceHashMap;

    NDFlowpathGenerator_t NDFlowpathGenerator;

    NDHttpReqRespCaptureSettings ndHttpReqCaptureSettings;
    NDHttpReqRespCaptureSettings ndHttpRespCaptureSettings;
    //NDHttpCaptureSettings_t NDHttpCaptureSettings;

    apr_hash_t* fpiToTLS;

    int instrumentSleep;
    int ndProxyMode;

    NDAutoDiscoveryHandler_t* NDAutoDiscoveryHandler;
    apr_thread_t* discover_thread_id;
    apr_socket_t* temp_connection;
    apr_socket_t* disSkt;
    lws_handler_t temp_lws_handler;

    //int  GloTimStmp;
    autoInstrumentation_t autoInstrumentation;
    apr_hash_t* methodAutoInstrumentation;

    httpBodyBtRule_t* httpBodyBtRule;
    NDBTHeaderBasedRule* header_rule;
    NDBTCustomRule custom_rule;
    ndlbTrie nd_trie_node;


    /*New */
    int allSlow;
    int allVerySlow;
    int maxStates;
    int skipCount;
    ndlbStateMachine stateMachine;
    ndlbStateMachineforHeader stateMachineHeader;
    long long int lastLogSentTime;
    socketInfo_t logSkt;

    NDAgentSetting_t NDAgentSetting;

    //   char conf_file[BUFFER_LEN];
    apr_hash_t* methodBasedBtHash;

    long long lastSentMetadataTimeStamp;
    NDClientManager_t NDClientManager;   //Working

    /*New */

    int init_flag;
    int InstrFileData_flag;
    int isRunTime;
    int dump11_runtime_profile;
    int isModifiedHashmap;

    NDInterfaceProcessor_t NDInterfaceProcessor;
    NDSQLProcessor_t NDSQLProcessor;
    long long TimeOut;             //Working


/*   char fileBasesKeywordInfo[_MAX_KW][1024];
     keywordInfo kywdInfo[_MAX_KW];
     httpRespBtRule_t *httpRespBtRule;
     */
     httpReqBtRule_t *httpReqBtRule;          //Issues with these

    apr_hash_t* methodAutoInsturment;

    keywordInfo kywdInfo[127];

    apr_hash_t* backendNameHashMap;
    DelayMethodPropProperties delayMethodProp;

    int dbBackendId;
    methodPropProperties* DefaultMethod;
    apr_hash_t* threadIdToThreadLocal;


    /*   int controlTraceLevel;
         int nd_mem_trace_level;
         int malloc_counter;
         int appLogTraceLevel;
         int agentTraceLevel;                //Can't support these as thread local

         //char autoSensor_err_buf[ERROR_BUFFER_SIZE];
        nioSettings_t *NDLogCollectorBB ;

    */

    int reqCount;
    int xPathCount;
    int g_tlsidx;

    // ***new*****/
    //char reportBuffer[MAX_REPORT_SIZE + 1]; 
    int nsize;
    long long ruleParserNsize;
    long long NDReqHeaderDataBTnsize;
    long long NDRespHeaderDataBTnsize;

    /*New */
    //int trace_level;

    //MTTraceLogKey* trace_log_key;

   //long long resourceId ;   
    apr_pool_t* control_pool;

  /******************
   Changes for AI
   ****************/

  int hash_count;
  autoInstrumentationStruct_t *autoInstrumentationStruct;
  autoInstrumentationStruct_t *autoInstrumentationStructFinal;
  //int isInBlackListFlg;
  //int autoDeInstrFlg;
  int countOfBlackListMethods;
  methodProperties *blackListEntries;
  /**********************
    AI Changes End
    ********************/

 /****** changes for AI  uploadDownload threads  *****/
  UploadDownloadRequest *uploadDownloadRequest;
  apr_thread_t *autoInstr_thread_id;
  apr_pool_t *ai_thread_pool;

  // Buffer for agent log to be sent to Proxy
  char *agentLogBuffer;
  int sendLogsToProxy;
  //HPLOG:LWS
  char lws_active;
  char proxy_lws_active;
  NDPerThreadData_t NDPerThreadData;
  int gFreeTLSCnt ;
  int gBusyTLSCnt ;


  NDPerThreadData_t* gFreeTLSHead ;
  NDPerThreadData_t* gFreeTLSTail ;
  TLSDataStruct* tlsdatastruct ;
  NDPerThreadData_t* gBusyTLSTail ;
  NDPerThreadData_t* gBusyTLSHead ;
  apr_hash_t *threadBasedModelMap;
  //NDMonitorDataModel *tlMonitorDataModel;
  NDASSettings_t  NDASSettings;
  NDSettings_t  NDSettings;
  apr_hash_t *ndTDHashMap;
  int total_count;
  //Protocol Negotiation Changes
  int supportedProtocolArray[5];   //This Supported Protocol Array is populated from agent Side and will never change
  int supportedProtocolNDCArray[5];   //This Supported Protocol Array is populated from NDC Side 
  int ActiveAgentProtocolIndex;
  supportedProtocols_t* supportedProtocols;
  supportedProtocols_t* supportedProtocolsNDC;
//  apr_hash_t* supportedProtocolsNDCMap;
 // apr_thread_mutex_t* supportedProtocolsLock;
 // apr_thread_mutex_t* supportedProtocolsNDCLock;

  apr_thread_t *control_thread_id;
  apr_hash_t* mapATD;

    struct callback_util control_util, bulkData_util, log_util;
    struct data_util_t data_util, as_util, discovery_util;

    nioSettings_t* NDLogCollectorBBLog;
    nioSettings_t* NDBCIAgentBBLog;

    nioSettings_t* writeListLog;
    nioSettings_t* writeListLastLog;
    int writeListSizeLog;

    nioSettings_t* readListLog;
    nioSettings_t* readListLastLog;
    int logReadListSizeLog;

    apr_thread_mutex_t* bufferWriteLock;
    apr_thread_mutex_t* bufferMoveLock;
    apr_thread_mutex_t *bufferWriteLockAS;
    apr_thread_mutex_t *bufferMoveLockAS;
    apr_thread_mutex_t* controlThreadTmpLock;

    int apptype; //0-tcp 1-udp
    int iTcpUdpMode;
    time_t udpPacketReceiveTime;
    apr_hash_t* udp_havoc_timeout;
}NDProxyInstance_t;


//structure to keep transaction data
//structure to keep transaction data
struct perThreadOps {
    //index/count to track transactions  
    unsigned short opCount;

    //any thread can reset max 10 transaction at a time
    unsigned short arrSize;
    struct threadOps* arrThreadOp;
    //struct threadOps arrThreadOp[NUM_THREAD_OPERATIONS]; //allocate dynamic memory, use unsigned short, 10

    //transaction reset should be thread safe
    apr_thread_mutex_t* threadOpLock;
    int total_operation_queued;
    int total_operation_processed;
    int total_operation_ignored;
    int total_pending_processe;
};
typedef struct udp_thread_storage {
    rudp_packet_wrapper* node;
    apr_sockaddr_t* saddr;
    apr_thread_mutex_t* thread_bufferReadLock;
    apr_thread_cond_t* thread_cond_var;
    NDProxyInstance_t* proxyInstance;
    unsigned short threadIndex;
    struct perThreadOps perThreadOpsVar;

}udp_thread_storage;



extern char gPool[256];//, gProcessName[256];
extern NDProxyInstance_t** NDProxyInstance;
//extern NDProxyInstance_t** NDProxyUdpInstance;
//extern NDProxyInstance_t *NDProxyTcpUdpInstance[20];
extern void ndProxyInit();
extern void NDTraceInit(char* process_name, char* pool_name_local);
//extern void sigsegv_handler(int sig);


#ifdef ND_AGENT_PROXY
#ifdef __unix__
extern __thread NDProxyInstance_t* tlndApplication;
#else
#ifdef __cplusplus
//extern "C" __declspec(thread) NDProxyInstance_t * tlndApplication;
#else
extern __declspec(thread) NDProxyInstance_t* tlndApplication;
#endif
#endif
#else
#ifdef __unix__
    #ifdef ND_PROXY_CONTROL
        extern __thread NDProxyInstance_t* tlndApplication;
    #else
        extern NDProxyInstance_t* tlndApplication;
    #endif
#else
#ifdef __cplusplus
extern "C" NDProxyInstance_t * tlndApplication;
#else
extern NDProxyInstance_t* tlndApplication;
#endif
#endif
#endif

#ifdef __unix__
  extern __thread unsigned short tlWorkerThreadId;
#else
  extern __declspec(thread) unsigned short tlWorkerThreadId;
#endif

/*
#ifdef __cplusplus__
extern thread_local NDProxyInstance_t* tlndApplication;
#else
extern __declspec(thread) NDProxyInstance_t* tlndApplication;
#endif

*/
/*
#ifdef __unix__
extern __thread NDProxyInstance_t  *tlndApplication;
#else
extern __declspec(thread) NDProxyInstance_t * tlndApplication;
#endif
*/


#define ndApplication tlndApplication
//void updateUDPClientDetails(int appindex, int newconn);
void closeUDPThread(NDProxyInstance_t  *ndProxyInstanceIndex);
//#include "../ndGlobalMacro.h"

#endif
