<%- @schemas.sort.each do |key, schema| -%>
<%= class_name(key) %>.php
<?php

declare(strict_types=1);

/**
 * This code was auto-generated by {this script}[https://github.com/cucumber/messages/blob/main/jsonschema/scripts/codegen.rb]
 */

namespace Cucumber\Messages;

use JsonSerializable;
use Cucumber\Messages\DecodingException\SchemaViolationException;

/**
 * Represents the <%= class_name(key) %> message in Cucumber's message protocol
 * @see https://github.com/cucumber/messages
 *
<%=- format_description(schema['description'], indent_string: '') -%> */
final class <%= class_name(key) %> implements JsonSerializable
{
    use JsonEncodingTrait;

    /**
     * Construct the <%= class_name(key) %> with all properties
     *
    <%- schema['properties'].each do |property_name, property| -%>
        <%- property_type = type_for(key, property_name, property) -%>
        <%- if property_type == 'array' -%>
     * @param <%= is_nullable(property_name, schema) ? '?' : '' %>list<<%= array_contents_type(key, property_name, property) %>> $<%= property_name %>
		<%- end -%>
    <%- end -%>
     */
    public function __construct(
    <%- schema['properties'].each do |property_name, property| -%>
        <%- property_type = type_for(key, property_name, property) -%>
        <%- if  property['description'] -%>

        /**
        <%= format_description(property['description']) %>
         */
        <%- end -%>
        public readonly <%= is_nullable(property_name, schema) ? '?' : '' %><%= property_type %> $<%= property_name %> = <%= default_value(class_name(key), property_name, property, schema) -%>,
    <%- end -%>
    ) {
    }

    /**
     * @throws SchemaViolationException
     *
     * @internal
     */
    public static function fromArray(array $arr): self
    {
        <%- schema['properties'].each do |property_name, property| -%>
        self::ensure<%= capitalize(property_name)%>($arr);
        <%- end -%>

        return new self(
            <%- schema['properties'].each do |property_name, property| -%>
            <%= constructor_for(key, property, property_name, schema, 'arr') %>,
            <%- end -%>
        );
    }
    <%- schema['properties'].each do |property_name, property| -%>

    /**
        <%- if is_scalar(property) -%>
     * @psalm-assert array{<%= property_name %><%- if (is_nullable(property_name, schema)) -%>?<%- end -%>: string|int|bool} $arr
        <%- else -%>
     * @psalm-assert array{<%= property_name %><%- if (is_nullable(property_name, schema)) -%>?<%- end -%>: array} $arr
        <%- end -%>
     */
    private static function ensure<%= capitalize(property_name)%>(array $arr): void
    {
        <%- if (!is_nullable(property_name, schema)) -%>
        if (!array_key_exists('<%= property_name %>', $arr)) {
            throw new SchemaViolationException('Property \'<%= property_name %>\' is required but was not found');
        }
        <%- end -%>
        <%- if(is_scalar(property)) -%>
        if (array_key_exists('<%= property_name %>', $arr) && is_array($arr['<%= property_name %>'])) {
            throw new SchemaViolationException('Property \'<%= property_name %>\' was array');
        }
        <%- else -%>
        if (array_key_exists('<%= property_name %>', $arr) && !is_array($arr['<%= property_name %>'])) {
            throw new SchemaViolationException('Property \'<%= property_name %>\' was not array');
        }
        <%- end -%>
    }
    <%- end -%>
}
<%- end -%>
