nooise 1.1.2

Ambient music generator for the terminal
use std::fmt::Display;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use update_informer::{Check, registry};

const UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(60 * 60 * 24);
const UPDATE_CHECK_TIMEOUT: Duration = Duration::from_secs(2);
const EXPLICIT_UPDATE_TIMEOUT: Duration = Duration::from_secs(5);

#[derive(Clone, Debug, Default)]
pub(crate) struct UpdateNotice {
    message: Arc<Mutex<Option<String>>>,
}

impl UpdateNotice {
    pub(crate) fn message(&self) -> Option<String> {
        self.message.lock().ok().and_then(|message| message.clone())
    }

    fn set_message(&self, message: String) {
        if let Ok(mut current) = self.message.lock() {
            *current = Some(message);
        }
    }
}

pub(crate) fn spawn_update_check(notice: UpdateNotice) {
    thread::spawn(move || {
        if let Ok(Some(version)) = check_latest(UPDATE_CHECK_INTERVAL, UPDATE_CHECK_TIMEOUT) {
            notice.set_message(format_update_message(version));
        }
    });
}

pub(crate) fn check_for_update() -> update_informer::Result<Option<update_informer::Version>> {
    check_latest(Duration::ZERO, EXPLICIT_UPDATE_TIMEOUT)
}

pub(crate) fn format_update_message(version: impl Display) -> String {
    format!("update {version} available: nooise update")
}

fn check_latest(
    interval: Duration,
    timeout: Duration,
) -> update_informer::Result<Option<update_informer::Version>> {
    update_informer::new(
        registry::Crates,
        env!("CARGO_PKG_NAME"),
        env!("CARGO_PKG_VERSION"),
    )
    .interval(interval)
    .timeout(timeout)
    .check_version()
}

#[cfg(test)]
mod tests {
    use super::{UpdateNotice, format_update_message};

    #[test]
    fn update_message_names_command() {
        assert_eq!(
            format_update_message("v1.2.3"),
            "update v1.2.3 available: nooise update"
        );
    }

    #[test]
    fn notice_starts_empty_and_stores_message() {
        let notice = UpdateNotice::default();
        assert_eq!(notice.message(), None);

        notice.set_message("update v1.2.3 available: nooise update".to_string());
        assert_eq!(
            notice.message(),
            Some("update v1.2.3 available: nooise update".to_string())
        );
    }
}