using System.Collections.Generic;
using System.Text.Json;

namespace Dacryptero.Data.Schema
{
    public class SchemaRole
    {
        public string Name { get; }

        public bool Abstract { get; }

        public string? Parent { get; }

        public Dictionary<string, SchemaAttribute> Attributes { get; }
            = new Dictionary<string, SchemaAttribute>();

        public SchemaRole(string name, bool @abstract, string? parent)
        {
            Name = name;
            Abstract = @abstract;
            Parent = parent;
        }

        public SchemaRole(JsonElement json)
        {
            Name = json.GetProperty("name").GetString() ?? "";
            Abstract = json.GetProperty("abstract").GetBoolean();
            Parent = json.TryGetProperty("parent", out JsonElement node) ?
                node.GetString() : null;
            foreach (var entry in json.GetProperty("attributes").EnumerateObject())
            {
                Attributes.Add(entry.Name, new SchemaAttribute(entry.Value));
            }
        }

        public SchemaRole Clone()
        {
            var role = new SchemaRole(Name, Abstract, Parent);
            foreach (var (name, attr) in Attributes)
                role.Attributes.Add(name, attr);
            return role;
        }

        public void Include(SchemaRole role)
        {
            foreach (var (name, attr) in role.Attributes)
                if (!Attributes.ContainsKey(name))
                    Attributes.Add(name, attr);
        }

        public void WriteTo(Utf8JsonWriter writer)
        {
            writer.WriteStartObject();
            writer.WriteString("name", Name);
            writer.WriteBoolean("abstract", Abstract);
            writer.WriteString("parent", Parent);
            writer.WriteStartObject("attributes");
            foreach (var (name, attr) in Attributes)
            {
                writer.WritePropertyName(name);
                attr.WriteTo(writer);
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }
    }
}