#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "service.hpp"
#include "message.h"

class MyService : public CService
{
  private:
    HANDLE hEventStop;
    HANDLE hThread;

    static DWORD WINAPI ThreadStartStatic (LPVOID);
    DWORD ThreadStart ();
        
  public:
    BOOL  ServiceStart (DWORD dwArgc, LPTSTR * lpszArgv);
    DWORD ServiceStop ();
};

// static thread function for Win32 API
DWORD WINAPI MyService::ThreadStartStatic (LPVOID param)
{
  MyService * pService = (MyService *) param;
  return pService -> ThreadStart ();
}

// member thread function for Win32 API
DWORD MyService::ThreadStart ()
{
  // this is the service work thread
  for (;;)
  {
    // Sleep some time, until Stop Event
    if (WaitForSingleObject (hEventStop, 1000) != WAIT_TIMEOUT)
      return 0L;

    // TODO: Work
  }
}

BOOL MyService::ServiceStart (DWORD dwArgc, LPTSTR * lpszArgv)
{
  dwArgc = 0; lpszArgv = NULL;

  DWORD tid;
  
  hEventStop = CreateEvent (NULL, FALSE, FALSE, NULL);

  if (hEventStop != INVALID_HANDLE_VALUE)
  {
    hThread = CreateThread (NULL, 8192, ThreadStartStatic, this, 0, &tid);

    if (hThread)
    {
      LogInfo(EVENTLOGMSG_SERVICE_STARTED);
      return TRUE;
    }
  }
  return FALSE;
}

DWORD MyService::ServiceStop ()
{
  SetEvent (hEventStop);
  WaitForSingleObject(hThread, INFINITE);   // wait for thread
  LogInfo(EVENTLOGMSG_SERVICE_STOPPED);     // eventlog info
  return 0;
}

int main (int argc, char **argv)
{
  enum { SVC_RUN, SVC_INSTALL, SVC_REMOVE};
  MyService service;
  int request;
  
  if (argc > 1 && (argv[1][0] == '-' || argv[1][0] == '/'))
  {
    if (strcmp (argv[1] + 1, "install") == 0)
      request = SVC_INSTALL;
    else if (strcmp (argv[1] + 1, "remove") == 0)
      request = SVC_REMOVE;
  }
  
  service.Init ("rsxntsvc", "RsxNT Service", SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN);

  if (request == SVC_INSTALL)
    service.CmdInstallService();

  else if (request == SVC_REMOVE)
    service.CmdRemoveService();

  else
    service.Run(argc, argv);
  
  return 0;
}

