using System.Text.Json.Nodes;
using System.Text.Json;

namespace AsyncApiRenderer.Data;

public abstract class JsonExampleNode
{
    public sealed class JsonObject : JsonExampleNode
    {
        public Dictionary<string, JsonExampleNode> Nodes { get; }
            = new Dictionary<string, JsonExampleNode>();

        public override JsonExampleNode Clone()
        {
            var copy = new JsonObject();
            foreach (var (key, node) in Nodes)
                copy.Nodes.Add(key, node.Clone());
            return copy;
        }

        public override void Write(Utf8JsonWriter writer)
        {
            writer.WriteStartObject();
            foreach (var (key, node) in Nodes)
            {
                writer.WritePropertyName(key);
                node.Write(writer);
            }
            writer.WriteEndObject();
        }
    }

    public sealed class JsonArray : JsonExampleNode
    {
        public List<JsonExampleNode> Nodes { get; }
            = new List<JsonExampleNode>();

        public override JsonExampleNode Clone()
        {
            var clone = new JsonArray();
            clone.Nodes.Capacity = Nodes.Capacity;
            foreach (var node in Nodes)
                clone.Nodes.Add(node.Clone());
            return clone;
        }

        public override void Write(Utf8JsonWriter writer)
        {
            writer.WriteStartArray();
            foreach (var item in Nodes)
                item.Write(writer);
            writer.WriteEndArray();
        }
    }

    public sealed class JsonValue : JsonExampleNode
    {
        public JsonNode? Node { get; set; }

        public override JsonExampleNode Clone()
        {
            return new JsonValue
            {
                Node = Node,
            };
        }

        public override void Write(Utf8JsonWriter writer)
        {
            if (Node is null)
                writer.WriteNullValue();
            else Node.WriteTo(writer);
        }
    }

    public abstract JsonExampleNode Clone();

    public abstract void Write(Utf8JsonWriter writer);

    public override string ToString()
    {
        using var m = new MemoryStream();
        using var w = new Utf8JsonWriter(m, new JsonWriterOptions
        {
            Indented = true,
        });
        Write(w);
        w.Flush();
        return System.Text.Encoding.UTF8.GetString(m.ToArray());
    }
}