#ifndef ESYSTEM_WIN32_H
#define ESYSTEM_WIN32_H

#include "eutils.h"

#include "earray.h"
#include "efunc.h"
#include "einthashof.h"

class esystemTimer
{
public:
//	CFRunLoopTimerRef tmref;
	UINT_PTR timerID;
	efunc callback;
	evararray data;
	double secs;
	double repeat;

	esystemTimer();
	~esystemTimer();
};

class esystemCallback;

class esystemCallbackArray
{
 public:
  int fd;
  int readCount;
  int writeCount;
  int acceptCount;
  HANDLE fileEvent;
  WSAEVENT readEvent;
  WSAEVENT writeEvent;
  WSAEVENT acceptEvent;

  ebasicarray<esystemCallback*> callbacks;
  esystemCallbackArray();
  ~esystemCallbackArray();
};

class esystemCallback
{
 public:
  esystemCallbackArray *cbarr;

  int lcount;

  bool readEnabled;
  evararray readData;
  efunc readCallback;

  bool writeEnabled;
  evararray writeData;
  efunc writeCallback;

  bool acceptEnabled;
  evararray acceptData;
  efunc acceptCallback;

  esystemCallback(esystemCallbackArray *cbarr);
  ~esystemCallback();
  
  void enableReadWrite();
  void enableRead();
  void enableWrite();
  void enableAccept();
  void disableReadWrite();
  void disableRead();
  void disableWrite();
  void disableAccept();
  void remove();
  void retain();
  void release();
};

class esystem
{
 public:
/*
  earray<HANDLE> fds;
  earray<efunc> funcs;
  ebasicarray<evar*> datas;
*/

  HINSTANCE hInstance;

  elonghashof<esystemTimer> timers;
  elonghashof<esystemCallbackArray> fdCallbacks;
  elonghashof<esystemCallbackArray> handleCallbacks;

  esystemCallback *waitcb;

  static esystem *cursystem;
  static int (*handleEvent)(HWND hWnd,UINT uMsg,DWORD wParam,DWORD lParam);

  estrarray getLocalAddresses();

  estr getExecutablePath() const;
  estr getHostname() const;
  int  getPID() const;

  long int getMemLimit();
  int getTotalRam();
  int getFreeRam();
  int getBufferRam();
  int getSharedRam();
  int getTotalSwap();
  int getFreeSwap();

  void setFrontProcess();

  static void __cdecl handleTimerCallback(HWND hWnd, UINT timerMsg, UINT_PTR timerID, DWORD epomili);
  esystemTimer* addTimer(const efunc& callback, const evararray& data, double secs, double repeat);

  bool processMessages();
  bool processMessagesWait();

  void process();
  void run();

  bool wait(HANDLE fHandle=0x00); 
  void waitSocket(int hsock);

  esystemCallback *addReadWriteCallback(int fd,const efunc& readCallback,const evararray& readData,const efunc& writeCallback,const evararray& writeData);
  esystemCallback *addWriteCallback(int fd,const efunc& func,const evararray& data);
  esystemCallback *addReadCallback(int fd,const efunc& func,const evararray& data);

  esystemCallback *addSocketReadWriteCallback(int fd,const efunc& readCallback,const evararray& readData,const efunc& writeCallback,const evararray& writeData);
  esystemCallback *addSocketWriteCallback(int fd,const efunc& func,const evararray& data);
  esystemCallback *addSocketReadCallback(int fd,const efunc& func,const evararray& data);
  esystemCallback *addSocketAcceptCallback(int fd,const efunc& func,const evararray& data);

  esystem();
  ~esystem();
};

esystem& getSystem();

#endif

