use std::fmt::{self, Arguments, Display, Formatter};

use owo_colors::OwoColorize;

macro_rules! declare_highlight {
    ($name:ident, $method:ident) => {
        pub struct $name<'a>(pub bool, pub Arguments<'a>);

        impl Display for $name<'_> {
            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
                if self.0 {
                    self.1.$method().fmt(f)
                } else {
                    self.1.fmt(f)
                }
            }
        }
    };
}

declare_highlight!(Dimmed, dimmed);
declare_highlight!(Bold, bold);
declare_highlight!(Accent, purple);
declare_highlight!(Failure, red);

macro_rules! highlight {
    ($color:expr, $name:ident $(, $($arg:tt)+)?) => {
        $crate::highlight::$name($color, format_args!($($($arg)+)?))
    };
}

macro_rules! hprint {
    ($($arg:tt)+) => {
        print!("{}", highlight!($($arg)+))
    };
}

macro_rules! hprintln {
    ($($arg:tt)+) => {{
        hprint!($($arg)+);
        println!();
    }};
}

macro_rules! hwrite {
    ($sink:expr, $($arg:tt)+) => {
        write!($sink, "{}", highlight!($($arg)+))
    };
}

macro_rules! hwriteln {
    ($sink:expr, $($arg:tt)+) => {
        hwrite!($sink, $($arg)+).and_then(|_| writeln!($sink))
    };
}
