/*-
 * syslog-rs - a syslog client translated from libc to rust
 * 
 * Copyright 2025 Aleksandr Morozov
 * 
 * The syslog-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */


use crate::
{
    error::SyRes, 
    formatters::SyslogFormatter, 
    AsyncSyslogDestination, 
    Priority, 
};

#[cfg(feature = "build_with_queue")]
use crate::SyslogDestination;

/// A syslog adapter to attach the async to sync queue.
#[cfg(feature = "build_with_queue")]
#[allow(async_fn_in_trait)]
pub trait AsyncSyslogQueueApi<F: SyslogFormatter, D: SyslogDestination>: std::fmt::Debug + Send + 'static
{
    /// Requests to connect to remote server.
    async fn a_connectlog(&mut self) -> SyRes<()>;

    /// Sets the logmask to filter out the syslog calls.
    /// 
    /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
    ///
    /// # Example
    ///
    /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
    ///
    /// or
    ///
    /// ~(LOG_MASK!(Priority::LOG_INFO))
    /// LOG_UPTO!(Priority::LOG_ERROR)
    async fn a_setlogmask(&self, logmask: i32) -> SyRes<i32>;

    /// Closes connection to the syslog server
    async fn a_closelog(&self) -> SyRes<()>;

    /// Similar to libc, syslog() sends data to syslog server.
    /// 
    /// # Arguments
    ///
    /// * `pri` - a priority [Priority]
    ///
    /// * `fmt` - a string message. In C exists a functions with
    ///     variable argumets amount. In Rust you should create your
    ///     own macros like format!() or use format!()]
    async fn a_syslog(&self, pri: Priority, fmt: F);

    /// This function can be used to update the facility name, for example
    /// after fork().
    /// 
    /// # Arguments
    /// 
    /// * `ident` - a new identity (up to 48 UTF8 chars)
    async fn a_change_identity(&self, ident: &str) -> SyRes<()>;

    /// Re-opens the connection to the syslog server. Can be used to 
    /// rotate logs(handle SIGHUP).
    /// 
    /// # Returns
    /// 
    /// A [Result] is retured as [SyRes].
    /// 
    /// * [Result::Ok] - with empty inner type.
    /// 
    /// * [Result::Err] - an error code and description 
    async fn a_reconnect(&self) -> SyRes<()>;

    /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
    /// the same variant (type) as current.
    async fn a_update_tap_data(&self, tap_data: D) -> SyRes<()>;
}


/// An implementation for the syslog "style" message handling (base).
pub(crate) trait AsyncSyslogApi<F: SyslogFormatter, D: AsyncSyslogDestination>: std::fmt::Debug + Send + 'static
{
    /// Requests to connect to remote server.
    async fn connectlog(&mut self) -> SyRes<()>;

    /// Sets the logmask to filter out the syslog calls.
    /// 
    /// See macroses [LOG_MASK] and [LOG_UPTO] to generate mask
    ///
    /// # Example
    ///
    /// LOG_MASK!(Priority::LOG_EMERG) | LOG_MASK!(Priority::LOG_ERROR)
    ///
    /// or
    ///
    /// ~(LOG_MASK!(Priority::LOG_INFO))
    /// LOG_UPTO!(Priority::LOG_ERROR)
    fn set_logmask(&mut self, logmask: i32) -> i32;

    /// Closes connection to the syslog server
    async fn closelog(&mut self) -> SyRes<()>;

    /// Similar to libc, syslog() sends data to syslog server.
    /// 
    /// # Arguments
    ///
    /// * `pri` - a priority [Priority]
    ///
    /// * `fmt` - a formatted [SyslogFormatter] message. In C exists a functions with
    ///     variable argumets amount. In Rust you should create your
    ///     own macros like format!() or use format!()]
    async fn vsyslog1(&mut self, pri: Priority, fmt: F);


    /// This function can be used to update the facility name, for example
    /// after fork().
    /// 
    /// # Arguments
    /// 
    /// * `ident` - a new identity (up to 48 UTF8 chars)
    fn change_identity(&mut self, ident: &str);

    /// Re-opens the connection to the syslog server. Can be used to 
    /// rotate logs(handle SIGHUP).
    /// 
    /// # Returns
    /// 
    /// A [Result] is retured as [SyRes].
    /// 
    /// * [Result::Ok] - with empty inner type.
    /// 
    /// * [Result::Err] - an error code and description 
    async fn reconnect(&mut self) -> SyRes<()>;

    /// Updates the instance's socket. `tap_data` [TapTypeData] should be of
    /// the same variant (type) as current.
    async fn update_tap_data(&mut self, tap_data: D) -> SyRes<()>;
}


