<?php

namespace apexl\Io\includes;

use apexl\ClassEngine\EngineSingleton;

/**
 * Relatively crude hook system, will need to be improved
 * Class Hook
 * @package apexl\Io\includes
 */
class Hook extends EngineSingleton
{
    //an array of callables, keyed by name
    protected static array $registeredCallbacks;
    protected static bool $disabled = false;

    public static function disable(): void
    {
        self::$disabled = true;
    }

    public static function enable(): void
    {
        self::$disabled = false;
    }

    public static function processHook(string $name, mixed $input = null, ...$args): mixed
    {
        $output = $input;

        if (self::canProcess($name)) {
            foreach (self::$registeredCallbacks[$name] as $callback) {
                $callable = self::toCallable($callback);
                if ($result = $callable($output, ...$args)) {
                    $output = $result;
                }
            }
        }

        return $output;
    }

    private static function canProcess(string $name): bool
    {
        return (!self::isDisabled() && self::hasCallback($name));
    }

    private static function isDisabled(): bool
    {
        return self::$disabled;
    }

    private static function hasCallback(string $name): bool
    {
        return isset(self::$registeredCallbacks[$name]);
    }

    private static function toCallable($callback): callable
    {
        if (is_callable($callback)) {
            return $callback;
        }

        // If the callback is not callable, we will assume that is declared in the 'old' manner
        // of `class:method`, where `method` is a public static method of `class`.
        return explode(':', $callback);
    }

    public static function registerCallback(string $name, $callback): void
    {
        self::$registeredCallbacks[$name][] = $callback;
    }

}

