1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use std::collections::HashMap;
use strum_macros::Display;

#[derive(Clone)]
pub enum VariableValues {
    Int(i32),
    Str(&'static str),
    Enum(&'static str),
    VecInt(Vec<i32>),
    VecStr(Vec<&'static str>),
    VecEnum(Vec<&'static str>),
}
type Fields = Vec<either::Either<&'static str, Args>>;
#[derive(Clone)]
pub struct Args {
    pub operation: String,
    pub fields: Fields,
    pub variables: Option<HashMap<&'static str, VariableValues>>,
}

pub fn tabs(level: usize) -> String {
    "\t".repeat(level)
}

// pub struct OperationArgs {
//     pub level: usize,
//     pub field: &'static str,
//     pub variables: Option<HashMap<&'static str, VariableValues>>,
//     pub sub_field: Option<bool>,
//     pub union: Option<bool>,
// }

#[derive(Display)]
#[strum(serialize_all = "snake_case")]
pub enum Operation {
    Query,
    Mutation,
    Subscription,
}

pub struct Builder {
    pub raw: String,
}

impl Builder {
    pub fn new(operation: Operation, opts: &Args) -> String {
        let subfields = Self::parse_sub_fields(&opts, 1).join("\n");
        let field = &opts.operation;
        format!("{operation} {{\n\t{field} {{\n{subfields}\n\t}}\n}}",)
    }
    fn parse_sub_fields(args: &Args, level: usize) -> Vec<String> {
        let level = level + 1;
        let tabs = tabs(level);
        args.fields
            .clone()
            .into_iter()
            .map(|arg| match arg {
                either::Either::Left(field) => {
                    format!("{tabs}{field}", field = field)
                }
                either::Either::Right(args) => {
                    let field = &args.operation;
                    let sub_field = Self::parse_sub_fields(&args, level).join("\n");
                    format!("{tabs}{field} {{\n{sub_field}\n{tabs}}}")
                }
            })
            .collect()
    }
}