<?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 Git message in Cucumber's message protocol
 * @see https://github.com/cucumber/messages
 *
 * Information about Git, provided by the Build/CI server as environment
 * variables. */
final class Git implements JsonSerializable
{
    use JsonEncodingTrait;

    /**
     * Construct the Git with all properties
     *
     */
    public function __construct(
        public readonly string $remote = '',
        public readonly string $revision = '',
        public readonly ?string $branch = null,
        public readonly ?string $tag = null,
    ) {
    }

    /**
     * @throws SchemaViolationException
     *
     * @internal
     */
    public static function fromArray(array $arr): self
    {
        self::ensureRemote($arr);
        self::ensureRevision($arr);
        self::ensureBranch($arr);
        self::ensureTag($arr);

        return new self(
            (string) $arr['remote'],
            (string) $arr['revision'],
            isset($arr['branch']) ? (string) $arr['branch'] : null,
            isset($arr['tag']) ? (string) $arr['tag'] : null,
        );
    }

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

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

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

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