#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>// open  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <unistd.h>  
#include <sys/wait.h>  
#include <signal.h>  
#include <chrono>
#include <spdlog/spdlog.h>  
#include <spdlog/sinks/rotating_file_sink.h>
#include <zmqpp/zmqpp.hpp>

using namespace std;

#define DEBUG(...) SPDLOG_LOGGER_DEBUG(spdlog::default_logger_raw(), __VA_ARGS__)
#define LOG(...) SPDLOG_LOGGER_INFO(spdlog::default_logger_raw(), __VA_ARGS__)
#define WARN(...) SPDLOG_LOGGER_WARN(spdlog::default_logger_raw(), __VA_ARGS__)
#define ERROR(...) SPDLOG_LOGGER_ERROR(spdlog::default_logger_raw(), __VA_ARGS__)

#define MAXFILE 65535  
  
volatile sig_atomic_t _running = 1;  
int fd;  
  
// signal handler  
void sigterm_handler(int arg)  
{  
    _running = 0;  
}  
  
int main()  
{  
    pid_t pid;  
  
    /* 屏蔽一些有关控制终端操作的信号 
     * 防止在守护进程没有正常运转起来时,因控制终端受到干扰退出或挂起 
     * */  
    signal(SIGINT,  SIG_IGN);// 终端中断  
    signal(SIGHUP,  SIG_IGN);// 连接挂断  
    signal(SIGQUIT, SIG_IGN);// 终端退出  
    signal(SIGPIPE, SIG_IGN);// 向无读进程的管道写数据  
    signal(SIGTTOU, SIG_IGN);// 后台程序尝试写操作  
    signal(SIGTTIN, SIG_IGN);// 后台程序尝试读操作  
    signal(SIGTERM, SIG_IGN);// 终止  
  
    // test  
    //sleep(20);// try cmd: ./test &; kill -s SIGTERM PID  
  
  
    // [1] fork child process and exit father process  
    pid = fork();  
    if(pid < 0)  
    {  
        perror("fork error!");  
        exit(1);  
    }  
    else if(pid > 0)  
    {  
        exit(0);  
    }  
  
    // [2] create a new session  
    setsid();  
  
    // [3] set current path  
    char szPath[1024] = {0};  
    if(getcwd(szPath, sizeof(szPath)) == NULL)  
    {  
        perror("getcwd");  
        exit(1);  
    }  
    else  
    {  
        chdir(szPath);  
        //printf("set current path succ [%s]\n", szPath);  
    }  
  
    // [4] umask 0  
    umask(0);  
  
    // [5] close useless fd  
    int i;  
    for (i = 3; i < MAXFILE; ++i)  
    {  
        close(i);  
    }  
  
    // [6] set termianl signal  
    signal(SIGTERM, sigterm_handler);  
  
    // Create a file rotating logger with 5 MB size max and 3 rotated files
    auto max_size = 1048576 * 5;
    auto max_files = 3;
    auto logger = spdlog::rotating_logger_mt("hjems-notifier", "./hjems-notifier.log", max_size, max_files);
    spdlog::set_default_logger(logger);
    // 遇到warn或者更高级别,比如err,critical 立即flush日志,防止丢失
    logger->flush_on(spdlog::level::warn);
    spdlog::flush_every(std::chrono::seconds(3));


    LOG("===== welcome to earth =====");  

    //const string endpoint = "tcp://139.196.5.21:44242";
    const string endpoint = "tcp://localhost:4242";

    // initialize the 0MQ context
    zmqpp::context context;

    // generate a push socket
    zmqpp::socket_type type = zmqpp::socket_type::push;
    zmqpp::socket socket (context, type);

    // open the connection
    LOG("Opening connection to %s",endpoint);
    socket.connect(endpoint);

    // do sth in loop  
    while(_running)  
    {  
        zmqpp::message message;
        // compose a message from a string and a number
        message << "Hello World!" << 42;
        socket.send(message);   
  
        LOG("send a message");

        usleep(1000*1000);// 1 s  
    }  

    LOG("===== I will be back =====");  
 
    return 0;  
}