// vlkbd
// daemon for VLKB services 

#include "rpc_amqp.hpp"

#include <iostream>
#include <stdexcept>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

// daemon related START
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
// daemon related END


#define DAEMON_NAME "vlkbd"

char dname[256];


using namespace std;

void signal_handler(int sig) {

   switch(sig){
      case SIGTERM:
         syslog(LOG_INFO,"received SIGTERM signal. Exiting ...");
         rpc_cleanup();
         exit(EXIT_SUCCESS);
         break;

      default:
         syslog(LOG_WARNING,"received unhandled signal (%d) %s",
               sig,strsignal(sig));
         break;

   }
}


void daemonize(void) {

   /* Our process ID and Session ID */
   pid_t pid, sid;

   /* Fork off the parent process */
   pid = fork();
   if (pid < 0) {
      exit(EXIT_FAILURE);
   }
   /* If we got a good PID, then
      we can exit the parent process. */
   if (pid > 0) {
      exit(EXIT_SUCCESS);
   }

   // insert signal handler here...
   signal(SIGTERM, signal_handler);

   /* Change the file mode mask */
   umask(0);

   // Open any logs here ...
   setlogmask(LOG_UPTO(LOG_INFO));
   sprintf(dname,"%s[%d]",DAEMON_NAME,getpid());
   openlog(dname, LOG_CONS, LOG_USER);
   syslog(LOG_INFO,"service started.");

   /* Create a new SID for the child process */
   sid = setsid();
   if (sid < 0) {
      /* Log the failure */
      exit(EXIT_FAILURE);
   }

   /* Change the current working directory */
   if ((chdir("/")) < 0) {
      /* Log the failure */
      exit(EXIT_FAILURE);
   }

   /* Keep the standard file descriptors 0, 1, 2 occupied
      so as no socket can have it; to guard the socket 
      against 'forgotten' printf's */

   freopen ("/dev/null", "r", stdin);
   freopen ("/dev/null", "w", stdout);
   freopen ("/dev/null", "w", stderr);

   /* Daemon-specific initialization goes here */
}



std::string base_name(std::string path)
{
   return path.substr(path.find_last_of("//") + 1); 
   // FIXME replace with basename
}



void usage(const string progname)
{
   cerr
      << "Usage: " << progname << " host port queuename conf-pathname [-t]" << endl
      << endl
      << " -t : stay on terminal, don't run as daemon" << endl
      << endl
      << "Version: " << VERSIONSTR << " " << BUILD << endl;
}



int main(int argc, char  *argv[])
{
   const std::string progname = base_name(argv[0]);

   if ((argc != 5) && (argc != 6))
   {
      usage(progname);
      return 1;
   }

   int daemon = (argc == 5);
   if(daemon)
      daemonize();

   // now stdin/out/err are redirected


   // start AMQP-consumer

   string hostname(argv[1]);
   int port = atoi(argv[2]);
   string queuename(argv[3]);
   string user_name("guest");
   string password("guest");
   string settings_pathname(argv[4]);
   //string settings_pathname("/etc/vlkb/datasets.conf");
   // FIXME uname passwd  put to conf file or args - cannot start without them

   try
   {
      rpc_run(user_name, password, hostname, port, queuename, settings_pathname);
   }
   catch (std::runtime_error const& e)
   {
      if(daemon)
         syslog(LOG_ERR, e.what());
      else
         std::cerr << "Runtime error: " << e.what() << std::endl;

      return 2;
   }

   syslog(LOG_INFO,"service stoped. Exiting...");

   return 0;
}
