import jdk.incubator.json.*;
import java.util.*;

public class JsonDemo {
    static final String ORDER = """
        {
          "id": 1042,
          "customer": {"name": "Asha Patil", "vip": true, "email": null},
          "items": [
            {"sku": "JV-100", "qty": 2, "price": 499.5},
            {"sku": "JV-200", "qty": 1, "price": 1250}
          ],
          "notes": "Deliver after 6 PM"
        }
        """;

    public static void main(String[] args) {
        System.out.println("== 1. Parse and navigate ==");
        JsonValue root = Json.parse(ORDER);
        System.out.println("root type     : " + root.getClass().getInterfaces()[0].getSimpleName());
        System.out.println("id            : " + root.get("id").asInt());
        System.out.println("customer.name : " + root.get("customer").get("name").asString());
        System.out.println("customer.vip  : " + root.get("customer").get("vip").asBoolean());
        double total = 0;
        for (JsonValue item : root.get("items").asList()) {
            total += item.get("qty").asInt() * item.get("price").asDouble();
        }
        System.out.println("order total   : " + total);

        System.out.println("\n== 2. Optional access ==");
        System.out.println("notes         : " + root.tryGet("notes").map(JsonValue::asString).orElse("(none)"));
        System.out.println("coupon        : " + root.tryGet("coupon").map(JsonValue::asString).orElse("(none)"));
        System.out.println("customer.email present? " + root.get("customer").tryGet("email").isPresent());
        System.out.println("customer.email class    : " + root.get("customer").get("email").getClass().getInterfaces()[0].getSimpleName());

        System.out.println("\n== 3. Wrong-type access fails fast ==");
        try { root.get("customer").asString(); }
        catch (RuntimeException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); }
        try { root.get("missing"); }
        catch (RuntimeException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); }
        try { root.get("items").get(7); }
        catch (RuntimeException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); }
        try { root.get("customer").get("name").asInt(); }
        catch (RuntimeException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); }
        try { root.get("id").asString(); }
        catch (RuntimeException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); }

        System.out.println("\n== 4. Parse errors ==");
        for (String bad : new String[] {
                "{\"a\": 1,}", "{\"a\": }", "[1, 2", "{'a': 1}", "{\"a\": 01}", "// c\n{}", "{\"a\": NaN}", "" }) {
            try { Json.parse(bad); System.out.println("OK (unexpected): " + bad); }
            catch (JsonParseException e) {
                System.out.printf("%-14s -> line %d, pos %d: %s%n", bad.replace("\n","\\n"), e.getErrorLine(), e.getErrorPosition(), e.getMessage());
            }
        }

        System.out.println("\n== 5. Generate ==");
        Map<String, JsonValue> m = new LinkedHashMap<>();
        m.put("name", JsonString.of("Ravi"));
        m.put("age", JsonNumber.of(31));
        m.put("active", JsonBoolean.of(true));
        m.put("tags", JsonArray.of(List.of(JsonString.of("java"), JsonString.of("json"))));
        m.put("spouse", JsonNull.of());
        JsonObject out = JsonObject.of(m);
        System.out.println(out);
        System.out.println(Json.toDisplayString(out, "  "));

        System.out.println("\n== 6. Numbers ==");
        JsonValue n = Json.parse("[1, 1.5, 12345678901234, 1e400, 0.1]");
        for (JsonValue v : n.asList()) {
            try { System.out.println(v + "  asDouble=" + v.asDouble()); }
            catch (RuntimeException e) { System.out.println(v + "  asDouble -> " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
        }
        try { n.get(1).asInt(); } catch (RuntimeException e) { System.out.println("1.5 asInt -> " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
        try { n.get(2).asInt(); } catch (RuntimeException e) { System.out.println("12345678901234 asInt -> " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
        System.out.println("12345678901234 asLong = " + n.get(2).asLong());

        System.out.println("\n== 7. Immutability and duplicates ==");
        try { root.asMap().put("x", JsonNull.of()); }
        catch (RuntimeException e) { System.out.println("asMap().put -> " + e.getClass().getSimpleName()); }
        try { System.out.println(Json.parse("{\"a\":1,\"a\":2}")); }
        catch (RuntimeException e) { System.out.println("duplicate key -> " + e.getClass().getSimpleName() + ": " + e.getMessage()); }
        System.out.println("key order: " + Json.parse("{\"z\":1,\"a\":2,\"m\":3}"));

        System.out.println("\n== 8. Unicode/escapes round-trip ==");
        JsonValue u = Json.parse("{\"s\": \"caf\\u00e9 \\\"q\\\" \\n tab\\t\"}");
        System.out.println(u.get("s").asString());
        System.out.println(u);
    }
}
