// Copyright 2021, The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Provides a universal logger interface that allows logging both on-device (using android_logger)
//! and on-host (using env_logger).
//! On-host, this allows the use of the RUST_LOG environment variable as documented in
//! https://docs.rs/env_logger.
use std::ffi::CString;
use std::sync::atomic::{AtomicBool, Ordering};

static LOGGER_INITIALIZED: AtomicBool = AtomicBool::new(false);

type FormatFn = Box<dyn Fn(&log::Record) -> String + Sync + Send>;

/// Logger configuration, opportunistically mapped to configuration parameters for android_logger
/// or env_logger where available.
#[derive(Default)]
pub struct Config<'a> {
    log_level: Option<log::Level>,
    custom_format: Option<FormatFn>,
    filter: Option<&'a str>,
    #[allow(dead_code)] // Field is only used on device, and ignored on host.
    tag: Option<CString>,
}

/// Based on android_logger::Config
impl<'a> Config<'a> {
    /// Change the minimum log level.
    ///
    /// All values above the set level are logged. For example, if
    /// `Warn` is set, the `Error` is logged too, but `Info` isn't.
    pub fn with_min_level(mut self, level: log::Level) -> Self {
        self.log_level = Some(level);
        self
    }

    /// Set a log tag. Only used on device.
    pub fn with_tag_on_device<S: Into<Vec<u8>>>(mut self, tag: S) -> Self {
        self.tag = Some(CString::new(tag).expect("Can't convert tag to CString"));
        self
    }

    /// Set the format function for formatting the log output.
    /// ```
    /// # use universal_logger::Config;
    /// universal_logger::init(
    ///     Config::default()
    ///         .with_min_level(log::Level::Trace)
    ///         .format(|record| format!("my_app: {}", record.args()))
    /// )
    /// ```
    pub fn format<F>(mut self, format: F) -> Self
    where
        F: Fn(&log::Record) -> String + Sync + Send + 'static,
    {
        self.custom_format = Some(Box::new(format));
        self
    }

    /// Set a filter, using the format specified in https://docs.rs/env_logger.
    pub fn with_filter(mut self, filter: &'a str) -> Self {
        self.filter = Some(filter);
        self
    }
}

/// Initializes logging on host. Returns false if logging is already initialized.
/// Config values take precedence over environment variables for host logging.
#[cfg(not(target_os = "android"))]
pub fn init(config: Config) -> bool {
    // Return immediately if the logger is already initialized.
    if LOGGER_INITIALIZED.fetch_or(true, Ordering::SeqCst) {
        return false;
    }

    let mut builder = env_logger::Builder::from_default_env();
    if let Some(log_level) = config.log_level {
        builder.filter_level(log_level.to_level_filter());
    }
    if let Some(custom_format) = config.custom_format {
        use std::io::Write; // Trait used by write!() macro, but not in Android code

        builder.format(move |f, r| {
            let formatted = custom_format(r);
            writeln!(f, "{}", formatted)
        });
    }
    if let Some(filter_str) = config.filter {
        builder.parse_filters(filter_str);
    }

    builder.init();
    true
}

/// Initializes logging on device. Returns false if logging is already initialized.
#[cfg(target_os = "android")]
pub fn init(config: Config) -> bool {
    // Return immediately if the logger is already initialized.
    if LOGGER_INITIALIZED.fetch_or(true, Ordering::SeqCst) {
        return false;
    }

    // We do not have access to the private variables in android_logger::Config, so we have to use
    // the builder instead.
    let mut builder = android_logger::Config::default();
    if let Some(log_level) = config.log_level {
        builder = builder.with_min_level(log_level);
    }
    if let Some(custom_format) = config.custom_format {
        builder = builder.format(move |f, r| {
            let formatted = custom_format(r);
            write!(f, "{}", formatted)
        });
    }
    if let Some(filter_str) = config.filter {
        let filter = env_logger::filter::Builder::new().parse(filter_str).build();
        builder = builder.with_filter(filter);
    }
    if let Some(tag) = config.tag {
        builder = builder.with_tag(tag);
    }

    android_logger::init_once(builder);
    true
}

/// Note that the majority of tests checking behavior are under the tests/ folder, as they all
/// require independent initialization steps. The local test module just performs some basic crash
/// testing without performing initialization.
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_with_min_level() {
        let config = Config::default()
            .with_min_level(log::Level::Trace)
            .with_min_level(log::Level::Error);

        assert_eq!(config.log_level, Some(log::Level::Error));
    }

    #[test]
    fn test_with_filter() {
        let filter = "debug,hello::crate=trace";
        let config = Config::default().with_filter(filter);

        assert_eq!(config.filter.unwrap(), filter)
    }

    #[test]
    fn test_with_tag_on_device() {
        let config = Config::default().with_tag_on_device("my_app");

        assert_eq!(config.tag.unwrap(), CString::new("my_app").unwrap());
    }

    #[test]
    fn test_format() {
        let config = Config::default().format(|record| format!("my_app: {}", record.args()));

        assert!(config.custom_format.is_some());
    }
}
