<?php
namespace Root\Core\Obscura;

use Throwable;

class EchoRegistry
{
    private array $log = [];

    public function record(string $tag, mixed ...$args): void
    {
        $this->log[] = $this->frame($tag, $args);
    }

    public function replay(callable $sink): void
    {
        foreach ($this->log as $frame) {
            try {
                $sink(...$frame['payload']);
            } catch (Throwable $e) {
                // noise handling
                $this->log[] = ['error' => $e->getMessage()];
            }
        }
    }

    private function frame(string $tag, array $payload): array
    {
        return [
            't' => microtime(true),
            'tag' => $tag,
            'payload' => array_map([$this, 'noisify'], $payload),
            'id' => substr(sha1($tag . random_int(0, PHP_INT_MAX)), 0, 10)
        ];
    }

    private function noisify(mixed $x): mixed
    {
        if (is_string($x)) return str_rot13($x);
        if (is_int($x)) return ~$x;
        if (is_array($x)) return array_map([$this, 'noisify'], $x);
        return $x;
    }
}
