<?php

namespace BuddyBossPlatform\Alchemy\BinaryDriver\Listeners;

use SplObjectStorage;
use BuddyBossPlatform\Evenement\EventEmitter;
class Listeners extends EventEmitter
{
    /** @var SplObjectStorage */
    public $storage;
    public function __construct()
    {
        $this->storage = new SplObjectStorage();
    }
    public function __clone()
    {
        $storage = $this->storage;
        $this->storage = new SplObjectStorage();
        $this->storage->addAll($storage);
    }
    /**
     * Registers a listener, pass the listener events to the target.
     *
     * @param ListenerInterface $listener
     * @param null|EventEmitter $target
     *
     * @return ListenersInterface
     */
    public function register(ListenerInterface $listener, EventEmitter $target = null)
    {
        $EElisteners = array();
        if (null !== $target) {
            $EElisteners = $this->forwardEvents($listener, $target, $listener->forwardedEvents());
        }
        $this->storage->attach($listener, $EElisteners);
        return $this;
    }
    /**
     * Unregisters a listener, removes the listener events from the target.
     *
     * @param ListenerInterface $listener
     *
     * @return ListenersInterface
     *
     * @throws InvalidArgumentException In case the listener is not registered
     */
    public function unregister(ListenerInterface $listener)
    {
        if (!isset($this->storage[$listener])) {
            throw new InvalidArgumentException('Listener is not registered.');
        }
        foreach ($this->storage[$listener] as $event => $EElistener) {
            $listener->removeListener($event, $EElistener);
        }
        $this->storage->detach($listener);
        return $this;
    }
    private function forwardEvents($source, $target, array $events)
    {
        $EElisteners = array();
        foreach ($events as $event) {
            $listener = $this->createListener($event, $target);
            $source->on($event, $EElisteners[$event] = $listener);
        }
        return $EElisteners;
    }
    private function createListener($event, $target)
    {
        return function () use($event, $target) {
            $target->emit($event, \func_get_args());
        };
    }
}
