<?php
declare(strict_types=1);

namespace Archive\StreamWrapper\Filter;

/**
 * Factory für die einfache Erstellung und Nutzung von Stream-Filtern
 */
final class StreamFilterFactory
{
    /**
     * Initialisiert alle Stream-Filter
     */
    public static function initialize(): void
    {
        StreamFilterRegistry::initializeDefaults();
    }

    /**
     * Erstellt einen Kompressions-Filter
     */
    public static function compression(int $level = 6): array
    {
        return [
            'name' => 'gzip.compress',
            'params' => ['level' => $level]
        ];
    }

    /**
     * Erstellt einen Dekompressions-Filter
     */
    public static function decompression(): array
    {
        return ['name' => 'gzip.decompress'];
    }

    /**
     * Erstellt einen Verschlüsselungs-Filter
     */
    public static function encryption(string $key, string $method = 'AES-256-CBC'): array
    {
        return [
            'name' => 'encrypt.aes256',
            'params' => [
                'key' => $key,
                'method' => $method
            ]
        ];
    }

    /**
     * Erstellt einen Entschlüsselungs-Filter
     */
    public static function decryption(string $key, string $method = 'AES-256-CBC'): array
    {
        return [
            'name' => 'decrypt.aes256',
            'params' => [
                'key' => $key,
                'method' => $method
            ]
        ];
    }

    /**
     * Erstellt einen JSON-Validierungs-Filter
     */
    public static function jsonValidation(bool $strict = true, bool $throwOnError = false): array
    {
        return [
            'name' => 'validate.json',
            'params' => [
                'strict' => $strict,
                'throw_on_error' => $throwOnError
            ]
        ];
    }

    /**
     * Erstellt einen Base64-Encoding-Filter
     */
    public static function base64Encode(bool $urlSafe = false): array
    {
        return [
            'name' => 'transform.base64encode',
            'params' => ['url_safe' => $urlSafe]
        ];
    }

    /**
     * Erstellt einen Access-Log-Filter
     */
    public static function accessLog(string $logFile = null): array
    {
        $params = [];
        if ($logFile) {
            $params['log_file'] = $logFile;
        }

        return [
            'name' => 'log.access',
            'params' => $params
        ];
    }

    /**
     * Wendet Filter auf einen Stream an
     */
    public static function applyFilters($stream, array $filters, int $mode = STREAM_FILTER_ALL): array
    {
        return StreamFilterRegistry::createFilterChain($stream, $filters, $mode);
    }

    /**
     * Wendet einen einzelnen Filter an
     */
    public static function applyFilter($stream, array $filterConfig, int $mode = STREAM_FILTER_ALL)
    {
        $filterName = $filterConfig['name'] ?? $filterConfig;
        $params = $filterConfig['params'] ?? [];

        return StreamFilterRegistry::appendFilter($stream, $filterName, $mode, $params);
    }

    /**
     * Erstellt einen Stream mit vordefinierten Filtern
     */
    public static function createFilteredStream(string $url, string $mode, array $filters = [], array $contextOptions = [])
    {
        $context = null;
        if (!empty($contextOptions)) {
            $context = stream_context_create($contextOptions);
        }

        $stream = fopen($url, $mode, false, $context);

        if ($stream && !empty($filters)) {
            self::applyFilters($stream, $filters);
        }

        return $stream;
    }

    /**
     * Vordefinierte Filter-Kombinationen
     */
    public static function secureDataFilter(string $encryptionKey): array
    {
        return [
            self::jsonValidation(true, true),
            self::compression(9),
            self::encryption($encryptionKey),
            self::accessLog()
        ];
    }

    public static function compressionFilter(int $level = 6): array
    {
        return [
            self::compression($level),
            self::accessLog()
        ];
    }

    public static function loggingFilter(string $logFile = null): array
    {
        return [
            self::accessLog($logFile)
        ];
    }
}
