use super::Pretty;
use crate::{json, test};

#[test]
fn should_pretty_print_root_null() {
    const JSON_IN: &str = "null";

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_IN);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_root_bool() {
    const JSON_IN: &str = "true";

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_IN);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_root_string() {
    const JSON_IN: &str = r#""one""#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_IN);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_escaped_str() {
    const JSON_IN: &str = r#""one\ntwo\u0021three\"four\"five""#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_IN);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_empty_array() {
    const JSON_IN: &str = "[]";
    const JSON_OUT: &str = "[
]";

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_string_array() {
    const JSON_IN: &str = r#"["a", "b", "c"]"#;
    const JSON_OUT: &str = r#"[
    "a",
    "b",
    "c"
]"#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_float_array() {
    const JSON_IN: &str =
        "[0.000564, 1.0, 3.14159, 2.71828182845904523536028747135266249775724709369995957496696]";
    const JSON_OUT: &str = "[
    0.000564,
    1.0,
    3.14159,
    2.71828182845904523536028747135266249775724709369995957496696
]";

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_empty_object() {
    const JSON_IN: &str = "{}";
    const JSON_OUT: &str = "{
}";

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_object_with_bools() {
    const JSON_IN: &str = r#"{"one":true,"two":false}"#;

    const JSON_OUT: &str = r#"{
    "one": true,
    "two": false
}"#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_object_with_nulls() {
    const JSON_IN: &str = r#"{"one":null,"two":null}"#;

    const JSON_OUT: &str = r#"{
    "one": null,
    "two": null
}"#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}

#[test]
fn should_pretty_print_root_object() {
    const JSON_IN: &str =
        r#"{"one": 1,"two": ["a", "b", "c"],"three": {"d": 4,"e": 5,"f": 6},"four":null}"#;

    const JSON_OUT: &str = r#"{
    "one": 1,
    "two": [
        "a",
        "b",
        "c"
    ],
    "three": {
        "d": 4,
        "e": 5,
        "f": 6
    },
    "four": null
}"#;

    test::setup();
    let doc = json::parse(JSON_IN.into()).unwrap();
    let pretty = Pretty::from_doc(&doc);

    let s = format!("{pretty}");
    assert_eq!(s, JSON_OUT);
    let _ignored = serde_json::from_str::<serde_json::Value>(&s).unwrap();
}
