use itertools::Itertools;
use crate::data::RPC;

pub fn ty_to_str(ty: &crate::data::Types) -> String {
    use crate::data::Types;

    match &ty {
        Types::String => "string".into(),
        Types::Bool => "boolean".into(),
        Types::F32 | Types::F64
        |Types::I8 | Types::I16 | Types::I32 | Types::I64
        |Types::U8 | Types::U16 | Types::U32 | Types::U64 => "number".into(),
        Types::Named(name) => name.into(),
        Types::Optional(inner) => format!("({}|null)", ty_to_str(inner)),
        Types::Array(inner) => format!("{}[]", ty_to_str(inner)),
        Types::Generic(_, _, _) => unreachable!()
    }
}

pub fn method_args(method: &crate::data::MethodTy) -> String {
    method.args.iter()
        .map(|arg| format!("{}: {}", arg.name, ty_to_str(&arg.ty)))
        .chain(method.ret_stream.then(|| format!("__cbk: (v: {}|null) => void", ty_to_str(method.ret.as_ref().unwrap()))))
        .join(", ")
}

pub fn method_ret(method: &crate::data::MethodTy) -> String {
    if method.ret_stream || method.ret.is_none() {
        String::new()
    } else {
        format!(": Promise<{}>", ty_to_str(method.ret.as_ref().unwrap()))
    }
}

pub fn gen(file_base_name: &std::path::PathBuf, rpc: &RPC) {
    let f = std::fs::File::create(file_base_name.with_extension("ts")).unwrap();
    crate::templates::typescript_client_ts(f, rpc).unwrap();
}