<?php

namespace Snaju\Inception\Event;

use Doctrine\Common\Annotations\AnnotationReader;
use Snaju\Inception\Annotation\EventHook;
use ReflectionMethod;

class EventManager
{

    public static $hooks = [];

    public static function addHook(string $eventName, callable $func, int $hookPriority = HookPriority::NORMAL)
    {
        if (!isset(self::$hooks[$eventName])) {
            self::$hooks[$eventName] = [];
        }

        $a = &self::$hooks[$eventName];

        $a[] = new EventHookObject($hookPriority, $func);

        // Sort the array
        usort($a, function ($a, $b) {
            if ($a instanceof EventHookObject && $b instanceof EventHookObject) {
                if ($a->getPriority() == $b->getPriority()) {
                    return 0;
                }

                if ($a->getPriority() > $b->getPriority()) {
                    return +1;
                } else {
                    return -1;
                }
            }

            return 0;
        });
    }

    public static function getHooks(string $eventName)
    {
        if (isset(self::$hooks[$eventName])) {
            return self::$hooks[$eventName];
        }

        return [];
    }

    public static function registerHooksFromMethods()
    {
        $reader = new AnnotationReader();
        $classes = get_declared_classes();
        foreach ($classes as $class) {
            $c = new \ReflectionClass($class);
            $methods = $c->getMethods(ReflectionMethod::IS_PUBLIC);
            foreach ($methods as $method) {
                if ($method instanceof ReflectionMethod && $method->isStatic()) {
                    $a = $reader->getMethodAnnotation($method, "Inception\Annotation\EventHook");
                    if ($a instanceof EventHook) {
                        $params = $method->getParameters();
                        if (count($params) == 1) {
                            foreach ($params as $param) {
                                if ($param instanceof \ReflectionParameter) {
                                    $type = $param->getType();
                                    if ($type instanceof \ReflectionType) {
                                        $n = $type->getName();
                                        $cc = new \ReflectionClass($n);
                                        if ($cc instanceof \ReflectionClass) {
                                            $p = $cc->getParentClass();
                                            if ($p instanceof \ReflectionClass) {
                                                if ($p->getShortName() == "Event") {
                                                    $cc->getName()::hook(function ($e) use ($c, $method) {
                                                        $nFinal = $c->getName();
                                                        return $nFinal::$method($e);
                                                    }, $a->priorirty);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    }

}

?>