<?php

declare(strict_types=1);

namespace AC\Deprecated;

use Closure;
use LogicException;
use ReflectionFunction;

class Hook
{
    private string $name;

    private string $version;

    private ?string $replacement;

    public function __construct(string $name, string $version, ?string $replacement = null)
    {
        $this->name = $name;
        $this->version = $version;
        $this->replacement = $replacement;
    }

    public function get_name(): string
    {
        return $this->name;
    }

    public function get_version(): string
    {
        return $this->version;
    }

    public function get_replacement(): string
    {
        if (null === $this->replacement) {
            throw new LogicException('Empty replacement');
        }

        return $this->replacement;
    }

    public function has_replacement(): bool
    {
        return null !== $this->replacement;
    }

    public function has_hook(): bool
    {
        return has_filter($this->name);
    }

    public function usage_count(): int
    {
        return count($this->get_callbacks() ?? []);
    }

    private function get_filter_callbacks(): array
    {
        global $wp_filter;

        return $wp_filter[$this->name]->callbacks ?? [];
    }

    public function get_callbacks(): ?array
    {
        $messages = [];

        foreach ($this->get_filter_callbacks() as $callback) {
            foreach ($callback as $cb) {
                $function = $cb['function'];

                // Function
                if (is_scalar($function)) {
                    $messages[] = sprintf('%s is called %s()', __('Function', 'codepress-admin-columns'), $function);
                    continue;
                }

                // Method
                if (is_array($function)) {
                    $class_name = is_object($function[0]) ? get_class($function[0]) : $function[0];
                    $messages[] = sprintf('%s::%s()', $class_name, $function[1]);
                    continue;
                }

                // Anonymous function
                if ($function instanceof Closure) {
                    $reflection = new ReflectionFunction($function);
                    $closure = $reflection->getClosureScopeClass();

                    $class_name = $closure
                        ? $closure->getName()
                        : null;

                    if ($class_name) {
                        $messages[] = sprintf(
                            '%s is called from %s',
                            __('Anonymous function', 'codepress-admin-columns'),
                            $class_name,
                        );

                        continue;
                    }

                    $messages[] = sprintf(
                        '%s is called from %s',
                        __('Anonymous Function', 'codepress-admin-columns'),
                        $reflection->getFileName(),
                    );
                }
            }
        }

        if (! $messages) {
            return null;
        }

        natcasesort($messages);

        return $messages;
    }

}
