use std::fmt::Display;

use log::{error, warn};

pub trait LogResult {
    type Ok;

    fn warn(self, s: &str) -> Option<Self::Ok>;
    fn error(self, s: &str) -> Option<Self::Ok>;
    fn panic(self, s: &str) -> Self::Ok;
}

impl<T, E> LogResult for Result<T, E>
where
    E: Display,
{
    type Ok = T;

    fn warn(self, s: &str) -> Option<T> {
        match self {
            Ok(val) => Some(val),
            Err(err) => {
                warn!("{}: {}", s, err);

                None
            }
        }
    }

    fn error(self, s: &str) -> Option<T> {
        match self {
            Ok(val) => Some(val),
            Err(err) => {
                error!("{}: {}", s, err);

                None
            }
        }
    }

    fn panic(self, s: &str) -> T {
        match self {
            Ok(val) => val,
            Err(err) => {
                error!("{}: {}", s, err);
                panic!("{}: {}", s, err);
            }
        }
    }
}
