<?php

declare (strict_types=1);
namespace OCA\Notifications\Vendor\SpomkyLabs\Pki\X509\GeneralName;

use OCA\Notifications\Vendor\SpomkyLabs\Pki\ASN1\Element;
use OCA\Notifications\Vendor\SpomkyLabs\Pki\ASN1\Type\TaggedType;
use OCA\Notifications\Vendor\SpomkyLabs\Pki\ASN1\Type\UnspecifiedType;
use Stringable;
use UnexpectedValueException;
/**
 * Implements *GeneralName* CHOICE with implicit tagging.
 *
 * @see https://tools.ietf.org/html/rfc5280#section-4.2.1.6
 */
abstract class GeneralName implements Stringable
{
    // GeneralName CHOICE tags
    public const TAG_OTHER_NAME = 0;
    public const TAG_RFC822_NAME = 1;
    public const TAG_DNS_NAME = 2;
    public const TAG_X400_ADDRESS = 3;
    public const TAG_DIRECTORY_NAME = 4;
    public const TAG_EDI_PARTY_NAME = 5;
    public const TAG_URI = 6;
    public const TAG_IP_ADDRESS = 7;
    public const TAG_REGISTERED_ID = 8;
    protected function __construct(protected int $tag)
    {
    }
    /**
     * Get general name as a string.
     */
    public function __toString(): string
    {
        return $this->string();
    }
    /**
     * Get string value of the type.
     */
    abstract public function string(): string;
    /**
     * Initialize concrete object from the chosen ASN.1 element.
     */
    abstract public static function fromChosenASN1(UnspecifiedType $el): self;
    /**
     * Initialize from ASN.1.
     */
    public static function fromASN1(TaggedType $el): self
    {
        return match ($el->tag()) {
            self::TAG_OTHER_NAME => OtherName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_RFC822_NAME => RFC822Name::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_DNS_NAME => DNSName::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_X400_ADDRESS => X400Address::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_DIRECTORY_NAME => DirectoryName::fromChosenASN1($el->asExplicit()),
            self::TAG_EDI_PARTY_NAME => EDIPartyName::fromChosenASN1($el->asImplicit(Element::TYPE_SEQUENCE)),
            self::TAG_URI => UniformResourceIdentifier::fromChosenASN1($el->asImplicit(Element::TYPE_IA5_STRING)),
            self::TAG_IP_ADDRESS => IPAddress::fromChosenASN1($el->asImplicit(Element::TYPE_OCTET_STRING)),
            self::TAG_REGISTERED_ID => RegisteredID::fromChosenASN1($el->asImplicit(Element::TYPE_OBJECT_IDENTIFIER)),
            default => throw new UnexpectedValueException('GeneralName type ' . $el->tag() . ' not supported.'),
        };
    }
    /**
     * Get type tag.
     */
    public function tag(): int
    {
        return $this->tag;
    }
    /**
     * Generate ASN.1 element.
     */
    public function toASN1(): Element
    {
        return $this->choiceASN1();
    }
    /**
     * Check whether GeneralName is equal to others.
     *
     * @param GeneralName $other GeneralName to compare to
     *
     * @return bool True if names are equal
     */
    public function equals(self $other): bool
    {
        if ($this->tag !== $other->tag) {
            return false;
        }
        if ($this->choiceASN1()->toDER() !== $other->choiceASN1()->toDER()) {
            return false;
        }
        return true;
    }
    /**
     * Get ASN.1 value in GeneralName CHOICE context.
     */
    abstract protected function choiceASN1(): TaggedType;
}