
use std::{sync::LazyLock, thread};
use std::time::Duration;

use syslog_rs::formatters::DefaultSyslogFormatter;
use syslog_rs::{SyslogApi, SyncSyslog};


use syslog_rs::{LogFacility, LogStat, Priority};

#[cfg(target_family = "unix")]
use syslog_rs::{SyslogLocal};

#[cfg(target_family = "windows")]
use syslog_rs::{WindowsEvent};

#[cfg(target_family = "unix")]
pub type DefaultLocalSyslogDestination = SyslogLocal;
#[cfg(target_family = "windows")]
pub type DefaultLocalSyslogDestination = WindowsEvent;

pub static SYSLOG: LazyLock<SyncSyslog> = LazyLock::new(|| 
    {
        #[cfg(target_family = "unix")]
        let syslog_provider = 
            SyslogLocal::new();

        #[cfg(target_family = "windows")]   
        let syslog_provider = 
            WindowsEvent::new();

        SyncSyslog::openlog(
            Some("example"), 
            LogStat::LOG_CONS | LogStat::LOG_PID, 
            LogFacility::LOG_DAEMON,
            syslog_provider
        )
        .unwrap()
    }
);

pub static SYSLOG2: LazyLock<SyncSyslog<DefaultSyslogFormatter, DefaultLocalSyslogDestination>> = LazyLock::new(|| 
    {
        #[cfg(target_family = "unix")]
        let syslog_provider = 
            SyslogLocal::new();

        #[cfg(target_family = "windows")]   
        let syslog_provider = 
            WindowsEvent::new();

        SyncSyslog
            ::<_, _>
            ::openlog_with(
            None, 
            LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
            LogFacility::LOG_DAEMON, syslog_provider
        )
        .unwrap()
    }
);

pub static SYSLOG3: LazyLock<SyncSyslog<DefaultSyslogFormatter, DefaultLocalSyslogDestination>> = LazyLock::new(|| 
    {
        #[cfg(target_family = "unix")]
        let syslog_provider = 
            SyslogLocal::new();

        #[cfg(target_family = "windows")]   
        let syslog_provider = 
            WindowsEvent::new();

        SyncSyslog
            ::<_, _>
            ::openlog_with(
                None, 
                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
                LogFacility::LOG_DAEMON, syslog_provider
            )
            .unwrap()
    }
);

macro_rules! logdebug 
{
    ($($arg:tt)*) => (
        SYSLOG.syslog(Priority::LOG_DEBUG, format!($($arg)*).into())
    )
}

macro_rules! logdebug2 
{
    ($($arg:tt)*) => (
        SYSLOG2.syslog(Priority::LOG_DEBUG, format!($($arg)*).into())
    )
}

pub fn main()
{
    logdebug2!("test program name!");

    
    logdebug!("test message1!");

    SYSLOG.change_identity(Some("example2")).unwrap();

    logdebug!("test message from new ident");

    #[cfg(target_family = "unix")]
    let syslog_provider = 
        SyslogLocal::new();

    #[cfg(target_family = "windows")]   
    let syslog_provider = 
        WindowsEvent::new();

    let new_syslog = 
        SyncSyslog
            ::<DefaultSyslogFormatter, DefaultLocalSyslogDestination>
            ::openlog_with(
                None, 
                LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
                LogFacility::LOG_DAEMON, syslog_provider
            )
            .unwrap();

    let c_new_syslog = new_syslog.clone();
    let thread_hndl = 
        std::thread::spawn(move || 
            {
                logdebug!("message from thread 1");
                std::thread::sleep(Duration::from_nanos(1000));
                logdebug!("message from thread 2");
                std::thread::sleep(Duration::from_nanos(1000));
                logdebug!("message from thread 3");
                std::thread::sleep(Duration::from_nanos(1000));
                logdebug!("message from thread 4");

                c_new_syslog.syslog(Priority::LOG_DEBUG, "test".into());
            }
        );

    let _ = thread_hndl.join();

    logdebug!("joined");
    thread::sleep(Duration::from_micros(10));

    return;
}
