// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]

extern crate proc_macro;
use proc_macro::{TokenStream, TokenTree as Tt};
use std::str::FromStr;

// String containing the current version number of the tip, i.e. "1.41.2"
static VERSION_NUMBER: &str = include_str!("../../../../../version");

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Version {
    major: i16,
    minor: i16,
    patch: i16,
}

fn parse_version(s: &str) -> Option<Version> {
    let mut digits = s.splitn(3, '.');
    let major = digits.next()?.parse().ok()?;
    let minor = digits.next()?.parse().ok()?;
    let patch = digits.next().unwrap_or("0").trim().parse().ok()?;
    Some(Version { major, minor, patch })
}

#[proc_macro_attribute]
/// Emits a #[cfg(version)] relative to the current one, so passing
/// -1 as argument on compiler 1.50 will emit #[cfg(version("1.49.0"))],
/// while 1 will emit #[cfg(version("1.51.0"))]
pub fn ver_cfg_rel(attr: TokenStream, input: TokenStream) -> TokenStream {
    let mut v_rel = None;
    for a in attr.into_iter() {
        match a {
            Tt::Literal(l) => {
                let mut s = l.to_string();
                let s = s.trim_matches('"');
                let v: i16 = s.parse().unwrap();
                v_rel = Some(v);
                break;
            },
            _ => panic!("{:?}", a),
        }
    }
    let v_rel = v_rel.unwrap();

    let mut v = parse_version(VERSION_NUMBER).unwrap();
    v.minor += v_rel;

    let attr_str = format!("#[cfg(version(\"{}.{}.{}\"))]", v.major, v.minor, v.patch);
    let mut res = Vec::<Tt>::new();
    res.extend(TokenStream::from_str(&attr_str).unwrap().into_iter());
    res.extend(input.into_iter());
    res.into_iter().collect()
}
