<?php

declare (strict_types=1);
namespace GuardDog\Vendor\Webauthn;

use GuardDog\Vendor\ParagonIE\ConstantTime\Base64UrlSafe;
use GuardDog\Vendor\Webauthn\Exception\InvalidDataException;
use GuardDog\Vendor\Webauthn\TokenBinding\TokenBinding;
use function array_key_exists;
use function is_array;
use function is_string;
use function sprintf;
use const JSON_THROW_ON_ERROR;
class CollectedClientData
{
    /**
     * @var mixed[]
     */
    public readonly array $data;
    public readonly string $type;
    public readonly string $challenge;
    public readonly string $origin;
    public readonly null|string $topOrigin;
    public readonly bool $crossOrigin;
    /**
     * @var mixed[]|null
     * @deprecated Since 4.3.0 and will be removed in 5.0.0
     * @infection-ignore-all
     */
    public readonly ?array $tokenBinding;
    /**
     * @param mixed[] $data
     */
    public function __construct(public readonly string $rawData, array $data)
    {
        $type = $data['type'] ?? '';
        is_string($type) && $type !== '' || throw InvalidDataException::create($data, 'Invalid parameter "type". Shall be a non-empty string.');
        $this->type = $type;
        $challenge = $data['challenge'] ?? '';
        is_string($challenge) || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall be a string.');
        $challenge = Base64UrlSafe::decodeNoPadding($challenge);
        $challenge !== '' || throw InvalidDataException::create($data, 'Invalid parameter "challenge". Shall not be empty.');
        $this->challenge = $challenge;
        $origin = $data['origin'] ?? '';
        is_string($origin) && $origin !== '' || throw InvalidDataException::create($data, 'Invalid parameter "origin". Shall be a non-empty string.');
        $this->origin = $origin;
        $this->topOrigin = $data['topOrigin'] ?? null;
        $this->crossOrigin = $data['crossOrigin'] ?? \false;
        $tokenBinding = $data['tokenBinding'] ?? null;
        $tokenBinding === null || is_array($tokenBinding) || throw InvalidDataException::create($data, 'Invalid parameter "tokenBinding". Shall be an object or .');
        $this->tokenBinding = $tokenBinding;
        $this->data = $data;
    }
    /**
     * @param mixed[] $data
     */
    public static function create(string $rawData, array $data): self
    {
        return new self($rawData, $data);
    }
    public static function createFormJson(string $data): self
    {
        $rawData = Base64UrlSafe::decodeNoPadding($data);
        $json = json_decode($rawData, \true, flags: JSON_THROW_ON_ERROR);
        is_array($json) || throw InvalidDataException::create($data, 'Invalid JSON data.');
        return self::create($rawData, $json);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getType(): string
    {
        return $this->type;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getChallenge(): string
    {
        return $this->challenge;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getOrigin(): string
    {
        return $this->origin;
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getCrossOrigin(): bool
    {
        return $this->crossOrigin;
    }
    /**
     * @deprecated Since 4.3.0 and will be removed in 5.0.0
     * @infection-ignore-all
     */
    public function getTokenBinding(): ?TokenBinding
    {
        return $this->tokenBinding === null ? null : TokenBinding::createFormArray($this->tokenBinding);
    }
    /**
     * @deprecated since 4.7.0. Please use the property directly.
     * @infection-ignore-all
     */
    public function getRawData(): string
    {
        return $this->rawData;
    }
    /**
     * @return string[]
     */
    public function all(): array
    {
        return array_keys($this->data);
    }
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->data);
    }
    public function get(string $key): mixed
    {
        if (!$this->has($key)) {
            throw InvalidDataException::create($this->data, sprintf('The key "%s" is missing', $key));
        }
        return $this->data[$key];
    }
}
