<?php
use Zend\Http\Request;
use Zend\Http\Response;;
use ZF\MvcAuth\Authentication\AdapterInterface;
use ZF\MvcAuth\Identity\IdentityInterface;
use ZF\MvcAuth\MvcAuthEvent;

class CompositeAdapter implements AdapterInterface
{
    private $adapters = [];

    private $matched;

    public function attach(AdapterInterface $adapter)
    {
        if (in_array($adapter, $this->adapters, true)) {
            return;
        }

        $this->adapters[] = $adapter;
    }

    public function provides()
    {
        return array_reduce($this->adapters, function ($carry, $adapter) {
            $provides = array_merge($carry, $adapter->provides());
            return array_unique($provides);
        }, []);
    }

    public function matches($type)
    {
        $this->matched = null;

        foreach ($this->adapters as $adapter) {
            $match = $adapter->matches($type);
            if ($match) {
                $this->matched = $adapter;
                return true;
            }
        }

        return false;
    }

    public function getTypeFromRequest(Request $request)
    {
        foreach ($this->adapters as $adapter) {
            $type = $adapter->getTypeFromRequest($request);
            if (false !== $type) {
                return $type;
            }
        }
        return false;
    }

    public function preAuth(Request $request, Response $response)
    {
        foreach ($this->adapters as $adapter) {
            $result = $adapter->preAuth($request, $response);
            if ($result instanceof Response) {
                return $result;
            }
        }
    }

    public function authenticate(Request $request, Response $response, MvcAuthEvent $mvcAuthEvent)
    {
        if (! $this->matched) {
            return false;
        }

        // Reset $matched so that subsequent calls fail
        $adapter = $this->matched;
        $this->matched = null;

        return $adapter->authenticate($request, $response, $mvcAuthEvent);
    }
}