<?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 Group message in Cucumber's message protocol
 * @see https://github.com/cucumber/messages
 *
 */
final class Group implements JsonSerializable
{
    use JsonEncodingTrait;

    /**
     * Construct the Group with all properties
     *
     * @param list<Group> $children
     */
    public function __construct(
        public readonly array $children = [],
        public readonly ?int $start = null,
        public readonly ?string $value = null,
    ) {
    }

    /**
     * @throws SchemaViolationException
     *
     * @internal
     */
    public static function fromArray(array $arr): self
    {
        self::ensureChildren($arr);
        self::ensureStart($arr);
        self::ensureValue($arr);

        return new self(
            array_values(array_map(fn (array $member) => Group::fromArray($member), $arr['children'])),
            isset($arr['start']) ? (int) $arr['start'] : null,
            isset($arr['value']) ? (string) $arr['value'] : null,
        );
    }

    /**
     * @psalm-assert array{children: array} $arr
     */
    private static function ensureChildren(array $arr): void
    {
        if (!array_key_exists('children', $arr)) {
            throw new SchemaViolationException('Property \'children\' is required but was not found');
        }
        if (array_key_exists('children', $arr) && !is_array($arr['children'])) {
            throw new SchemaViolationException('Property \'children\' was not array');
        }
    }

    /**
     * @psalm-assert array{start?: string|int|bool} $arr
     */
    private static function ensureStart(array $arr): void
    {
        if (array_key_exists('start', $arr) && is_array($arr['start'])) {
            throw new SchemaViolationException('Property \'start\' was array');
        }
    }

    /**
     * @psalm-assert array{value?: string|int|bool} $arr
     */
    private static function ensureValue(array $arr): void
    {
        if (array_key_exists('value', $arr) && is_array($arr['value'])) {
            throw new SchemaViolationException('Property \'value\' was array');
        }
    }
}
