// Auto-generated by BoltFFI. Do not edit.
package {{ package_name }};

{{ self::javadoc_block(enumeration.doc, "") }}public abstract class {{ enumeration.class_name }}{% if enumeration.is_error() %} extends RuntimeException{% endif %} {
{%- if enumeration.is_error() %}
    protected {{ enumeration.class_name }}(String message) {
        super(message);
    }
{%- else %}
    private {{ enumeration.class_name }}() {}
{%- endif %}
{%- for variant in enumeration.variants %}
{%- if variant.is_unit() %}

{{ self::javadoc_block(variant.doc, "    ") }}    public static final class {{ variant.name }} extends {{ enumeration.class_name }} {
        public static final {{ variant.name }} INSTANCE = new {{ variant.name }}();
        private {{ variant.name }}() {
{%- if enumeration.is_error() %}
            super("{{ enumeration.class_name }}.{{ variant.name }}");
{%- endif %}
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof {{ variant.name }};
        }

        @Override
        public int hashCode() {
            return {{ variant.tag }};
        }

        @Override
        public String toString() {
            return "{{ enumeration.class_name }}.{{ variant.name }}";
        }
    }
{%- else %}

{{ self::javadoc_block(variant.doc, "    ") }}    public static final class {{ variant.name }} extends {{ enumeration.class_name }} {
{%- for field in variant.fields %}
        public final {{ field.java_type }} {{ field.name }};
{%- endfor %}

        public {{ variant.name }}({% for field in variant.fields %}{{ field.java_type }} {{ field.name }}{% if !loop.last %}, {% endif %}{% endfor %}) {
{%- if enumeration.is_error() %}
{%- match variant.message_field_name() %}
{%- when Some with (message_field_name) %}
            super({{ message_field_name }});
{%- when None %}
            super("{{ enumeration.class_name }}.{{ variant.name }}");
{%- endmatch %}
{%- endif %}
{%- for field in variant.fields %}
            this.{{ field.name }} = {{ field.name }};
{%- endfor %}
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (!(obj instanceof {{ variant.name }})) return false;
            {{ variant.name }} other = ({{ variant.name }}) obj;
            return {% for field in variant.fields %}{{ field.equals_expr }}{% if !loop.last %} && {% endif %}{% endfor %};
        }

        @Override
        public int hashCode() {
            int result = 1;
{%- for field in variant.fields %}
            result = 31 * result + {{ field.hash_expr }};
{%- endfor %}
            return result;
        }

        @Override
        public String toString() {
            return "{{ enumeration.class_name }}.{{ variant.name }}{" +
{%- for field in variant.fields %}
                "{% if loop.first %}{% else %}, {% endif %}{{ field.name }}=" + {{ field.name }}{% if !loop.last %} +{% else %} +{% endif %}
{%- endfor %}
                '}';
        }
    }
{%- endif %}
{%- endfor %}

{%- for ctor in enumeration.constructors %}
{% include "render_java/value_type_constructor.txt" %}
{%- endfor %}

{%- for method in enumeration.methods %}
{% include "render_java/value_type_method.txt" %}
{%- endfor %}

    static {{ enumeration.class_name }} decode(WireReader reader) {
        int tag = reader.readI32();
        switch (tag) {
{%- for variant in enumeration.variants %}
{%- if variant.is_unit() %}
            case {{ variant.tag }}: return {{ variant.name }}.INSTANCE;
{%- else %}
            case {{ variant.tag }}: return new {{ variant.name }}(
{%- for field in variant.fields %}
                {{ field.wire_decode_expr }}{% if !loop.last %},{% endif %}
{%- endfor %}
            );
{%- endif %}
{%- endfor %}
            default: throw new RuntimeException("Unknown {{ enumeration.class_name }} tag: " + tag);
        }
    }

    int wireEncodedSize() {
{%- for variant in enumeration.variants %}
        if (this instanceof {{ variant.name }}) {
{%- if variant.is_unit() %}
            return 4;
{%- else %}
            {{ variant.name }} _v = ({{ variant.name }}) this;
            return 4 + {% for field in variant.fields %}{{ field.wire_size_expr }}{% if !loop.last %} + {% endif %}{% endfor %};
{%- endif %}
        }
{%- endfor %}
        throw new RuntimeException("Unknown {{ enumeration.class_name }} subtype");
    }

    void wireEncodeTo(WireWriter wire) {
{%- for variant in enumeration.variants %}
        if (this instanceof {{ variant.name }}) {
{%- if variant.is_unit() %}
            wire.writeI32({{ variant.tag }});
            return;
{%- else %}
            {{ variant.name }} _v = ({{ variant.name }}) this;
            wire.writeI32({{ variant.tag }});
{%- for field in variant.fields %}
            {{ field.wire_encode_expr }};
{%- endfor %}
            return;
{%- endif %}
        }
{%- endfor %}
        throw new RuntimeException("Unknown {{ enumeration.class_name }} subtype");
    }
}
