<?php

declare (strict_types=1);
namespace OCA\Talk\Vendor\CuyZ\Valinor\Mapper\Object;

use Countable;
use OCA\Talk\Vendor\CuyZ\Valinor\Definition\Parameters;
use OCA\Talk\Vendor\CuyZ\Valinor\Definition\Properties;
use OCA\Talk\Vendor\CuyZ\Valinor\Type\Types\ShapedArrayElement;
use OCA\Talk\Vendor\CuyZ\Valinor\Type\Types\ShapedArrayType;
use OCA\Talk\Vendor\CuyZ\Valinor\Type\Types\StringValueType;
use IteratorAggregate;
use Traversable;
use function array_diff_key;
use function array_keys;
use function array_map;
use function array_values;
use function count;
/**
 * @internal
 *
 * @implements IteratorAggregate<Argument>
 */
final readonly class Arguments implements IteratorAggregate, Countable
{
    /** @var array<string, Argument> */
    private array $arguments;
    private ShapedArrayType $shapedArray;
    public function __construct(Argument ...$arguments)
    {
        $args = [];
        foreach ($arguments as $argument) {
            $args[$argument->name()] = $argument;
        }
        $this->arguments = $args;
        $this->shapedArray = new ShapedArrayType(elements: array_map(static fn(Argument $argument) => new ShapedArrayElement(key: new StringValueType($argument->name()), type: $argument->type(), optional: !$argument->isRequired(), attributes: $argument->attributes()), $this->arguments), isUnsealed: false, unsealedType: null);
    }
    public static function fromParameters(Parameters $parameters): self
    {
        return new self(...array_map(Argument::fromParameter(...), [...$parameters]));
    }
    public static function fromProperties(Properties $properties): self
    {
        return new self(...array_map(Argument::fromProperty(...), [...$properties]));
    }
    public function at(int $index): Argument
    {
        return array_values($this->arguments)[$index];
    }
    /**
     * @return list<string>
     */
    public function names(): array
    {
        return array_keys($this->arguments);
    }
    public function merge(self $other): self
    {
        return new self(...$this->arguments, ...array_diff_key($other->arguments, $this->arguments));
    }
    public function toShapedArray(): ShapedArrayType
    {
        return $this->shapedArray;
    }
    /**
     * @return array<string, Argument>
     */
    public function toArray(): array
    {
        return $this->arguments;
    }
    public function count(): int
    {
        return count($this->arguments);
    }
    /**
     * @return Traversable<Argument>
     */
    public function getIterator(): Traversable
    {
        yield from $this->arguments;
    }
}