#include "ltrsrv_daemon.h"

#include "config.h"
#include "ltrsrv_log.h"
#include "ltrsrv_defs.h"
#include "ltrsrv_opt_parse.h"


#if defined HAVE_LIBDAEMON && defined LTRD_DAEMON_ENABLED
#include <libdaemon/daemon.h>
#endif

#if defined __QNX__ && defined LTRD_DAEMON_ENABLED
    #include <sys/procmgr.h>
#endif


extern void ltrsrv_setup_sighandlers(void);

#ifdef HAVE_LIBDAEMON

    const char* ltrsrv_pid_file_proc(void) {
        return g_opts.pid_file;
    }
    /* демонизация процесса - делается fork() в дочернем процессе закрываются
       все хендлы, проверяется pid-файл и прочие стандартные процедуры.
       is_daemon определяет, находимся мы в основном процессе, который должен
       сразу завершится после создания дочернего, или в дочернем (который и является демоном) */
    int ltrsrv_daemon_start(void) {
        pid_t pid;
        int err = 0;

        daemon_log_ident = "ltrd";
        daemon_pid_file_proc = ltrsrv_pid_file_proc;

        if ((daemon_reset_sigs(-1) < 0) || (daemon_unblock_sigs(-1) < 0)) {
            err = LTRSRV_ERR_SIGNAL_RESET;
            ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER,err,"Initialization error");
        }

        if (!err && (pid = daemon_pid_file_is_running()) >= 0) {
            err = LTRSRV_ERR_ALREADY_RUNNING;
            ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER,err, "Daemon already running on PID file %u\n", pid);
        }

        /* Prepare for return value passing from the initialization procedure of the daemon process */
        if (!err && (daemon_retval_init() < 0)) {
            err = LTRSRV_ERR_CREATE_PIPE;
            ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER, err,"Initialization error");
        }

        /* Do the fork */
        if (!err) {
            if ((pid = daemon_fork()) < 0) {
                /* Exit on error */
                daemon_retval_done();
                err = LTRSRV_ERR_DAEMONIZE_ERROR;
                ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER, err,"Initialization error");
            } else if (pid) {
                /* The parent */
                /* Wait for 2 seconds for the return value passed from the daemon process */
                if ((err = daemon_retval_wait(2)) ==-1) {
                    daemon_log(LOG_ERR, "Could not receive return value from daemon process");
                    err = LTRSRV_ERR_DAEMONIZE_ERROR;
                } else if (err !=0) {
                    daemon_log(LOG_ERR, "Daemon returned %i as return value.", err);
                }
            } else {
                /* Close FDs */
                if (daemon_close_all(-1) < 0) {
                    err = LTRSRV_ERR_CLOSE_DESCR;
                    ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER,err,"Initialization error");
                }

                /* Create the PID file */
                if (!err && (daemon_pid_file_create() < 0)) {
                    err = LTRSRV_ERR_CREATE_PIDFILE;
                    ltrsrv_log_rec(LTRSRV_LOGLVL_ERR_FATAL, LTRSRV_LOGSRC_SERVER,err,"Initialization error");
                }

                /*... do some further init work here */
                ltrsrv_setup_sighandlers();

                /* Send OK to parent process */
                daemon_retval_send(err);

                daemon_main();
            }
        }
        return err;
    }

    void ltrsrv_daemon_close(void) {
        daemon_retval_send(255);
        daemon_signal_done();
        daemon_pid_file_remove();
    }

#else

    int ltrsrv_daemon_start(void) {
        int err = 0;
    #ifdef __QNX__
        err = procmgr_daemon(EXIT_SUCCESS, 0);
    #else
        #error "Unsupport daemon mode"
    #endif

        if (!err)
            ltrsrv_setup_sighandlers();

        if (!err)
            err = daemon_main();
        return err;
    }


    void ltrsrv_daemon_close(void) {

    }

#endif

int ltrsrv_daemon_svc_op(t_ltrd_svc_op op) {
    return LTRSRV_ERR_INVALID_SVC_OP;
}
