<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace GDAVSCOPE\League\Uri\Components;

use BackedEnum;
use GDAVSCOPE\League\Uri\Contracts\Conditionable;
use GDAVSCOPE\League\Uri\Contracts\Transformable;
use GDAVSCOPE\League\Uri\Contracts\UriComponentInterface;
use GDAVSCOPE\League\Uri\Contracts\UriInterface;
use GDAVSCOPE\League\Uri\Encoder;
use GDAVSCOPE\League\Uri\Exceptions\SyntaxError;
use GDAVSCOPE\League\Uri\Modifier;
use GDAVSCOPE\League\Uri\Uri;
use GDAVSCOPE\Psr\Http\Message\UriInterface as Psr7UriInterface;
use Stringable;
use GDAVSCOPE\Uri\Rfc3986\Uri as Rfc3986Uri;
use GDAVSCOPE\Uri\WhatWg\Url as WhatWgUrl;
use function is_bool;
use function preg_match;
use function sprintf;
abstract class Component implements UriComponentInterface, Conditionable, Transformable
{
    protected const REGEXP_INVALID_URI_CHARS = '/[\x00-\x1f\x7f]/';
    abstract public function value(): ?string;
    public function jsonSerialize(): ?string
    {
        return $this->value();
    }
    public function toString(): string
    {
        return $this->value() ?? '';
    }
    public function __toString(): string
    {
        return $this->toString();
    }
    public function getUriComponent(): string
    {
        return $this->toString();
    }
    final protected static function filterUri(WhatWgUrl|Rfc3986Uri|BackedEnum|Stringable|string $uri): WhatWgUrl|Rfc3986Uri|UriInterface|Psr7UriInterface
    {
        if ($uri instanceof Modifier) {
            return $uri->unwrap();
        }
        if ($uri instanceof Rfc3986Uri || $uri instanceof WhatWgUrl || $uri instanceof PSR7UriInterface || $uri instanceof UriInterface) {
            return $uri;
        }
        return Uri::new($uri);
    }
    /**
     * Validate the component content.
     */
    protected function validateComponent(BackedEnum|Stringable|int|string|null $component): ?string
    {
        return Encoder::decodeNecessary($component);
    }
    /**
     * Filter the input component.
     *
     * @throws SyntaxError If the component cannot be converted to a string or null
     */
    final protected static function filterComponent(BackedEnum|Stringable|int|string|null $component): ?string
    {
        if ($component instanceof UriComponentInterface) {
            $component = $component->value();
        }
        if ($component instanceof BackedEnum) {
            $component = (string) $component->value;
        }
        return match (\true) {
            null === $component => null,
            1 === preg_match(self::REGEXP_INVALID_URI_CHARS, (string) $component) => throw new SyntaxError(sprintf('Invalid component string: %s.', $component)),
            default => (string) $component,
        };
    }
    final public function when(callable|bool $condition, callable $onSuccess, ?callable $onFail = null): static
    {
        if (!is_bool($condition)) {
            $condition = $condition($this);
        }
        return match (\true) {
            $condition => $onSuccess($this),
            null !== $onFail => $onFail($this),
            default => $this,
        } ?? $this;
    }
    final public function transform(callable $callback): static
    {
        return $callback($this);
    }
}
