#ifndef ESYSTEM_LINUX_H
#define ESYSTEM_LINUX_H

#include "eutils-config.h"

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

#include <signal.h>

class esystemCallback;

class esystemCallbackArray
{
 public:
  int fd;
  int readCount;
  int writeCount;
  ebasicarray<esystemCallback*> callbacks;
  esystemCallbackArray();
};

class esystemCallback
{
 public:
  esystemCallbackArray *cbarr;

  int lcount;

  bool readEnabled;
  evararray readData;
  efunc readCallback;

  bool writeEnabled;
  evararray writeData;
  efunc writeCallback;

  esystemCallback(esystemCallbackArray *cbarr);
  ~esystemCallback();

  void enableReadWrite();
  void enableRead();
  void enableWrite();
  void disableReadWrite();
  void disableRead();
  void disableWrite();
  void remove();
  void retain();
  void release();
};

class esystemTimer
{
 public:
  timer_t timer;
  efunc callback;
  evararray data;
};

class esystem
{
 public:
  einthashof<esystemCallbackArray> fdCallbacks;
  earrayof<esystemTimer,int> timers;

  static esystem *cursystem;

  esystem();

  void process();
  void run();

  void setFrontProcess(); // needed in OSX (maybe windows) to bring focus to application, not used in linux, or should be part of windows/UI system in edlibs

  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 addTimer(const efunc& func,const evararray& args,double secs,double repeat);
  static void handleTimerSignal(int signal,siginfo_t *si,void *data);

  static void handleInterruptSignal(int signal,siginfo_t *si,void *data);

  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);

  inline esystemCallback *addSocketReadWriteCallback(int fd,const efunc& readCallback,const evararray& readData,const efunc& writeCallback,const evararray& writeData) { return(addReadWriteCallback(fd,readCallback,readData,writeCallback,writeData)); }
  inline esystemCallback *addSocketWriteCallback(int fd,const efunc& func,const evararray& data) { return(addWriteCallback(fd,func,data)); }
  inline esystemCallback *addSocketReadCallback(int fd,const efunc& func,const evararray& data) { return(addReadCallback(fd,func,data)); }
  inline esystemCallback *addSocketAcceptCallback(int fd,const efunc& func,const evararray& data) { return(addReadCallback(fd,func,data)); }

  void wait(int fd=-1);  
  void waitSocket(int fd=-1) { wait(fd); }
};

esystem& getSystem();

#endif

