<?php

namespace WPDesk\ApiClient\Client;

use Psr\SimpleCache\CacheInterface;
use WPDesk\Cache\CacheDispatcher;
use WPDesk\Cache\CacheItemCreator;
use WPDesk\Cache\CacheItemVerifier;
use WPDesk\HttpClient\HttpClient;
use WPDesk\ApiClient\Request\Request;
use WPDesk\ApiClient\Response\Response;
use WPDesk\ApiClient\Serializer\Serializer;

class CachedClient implements Client, CacheItemCreator, CacheItemVerifier
{

    /** @var Client */
    private $client;

    /** @var CacheInterface */
    private $cache;

    /**
     * @var CacheDispatcher
     */
    private $cacheDispatcher;

    /**
     * CachedClient constructor.
     * @param Client $decorated Decorated client
     * @param CacheInterface $cache
     */
    public function __construct(Client $decorated, CacheInterface $cache)
    {
        $this->client = $decorated;
        $this->cache = $cache;
        $this->cacheDispatcher = new CacheDispatcher($cache, [new RequestCacheInfoResolver()]);
    }

    /**
     * Create item to cache.
     *
     * @param Request $request
     * @return Response
     */
    public function createCacheItem($request)
    {
        return $this->client->sendRequest($request);
    }

    /**
     * Verify cache item.
     *
     * @param $object
     * @return Response;
     */
    public function getVerifiedItemOrNull($object)
    {
        if ($object instanceof Response) {
            return $object;
        }
        return null;
    }

    /**
     * Send request.
     *
     * @param Request $request
     * @return mixed|Response
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function sendRequest(Request $request)
    {
        $response = $this->cacheDispatcher->dispatch($request, $this, $this);
        return $response;
    }

    /**
     * @return HttpClient
     */
    public function getHttpClient()
    {
        return $this->client->getHttpClient();
    }

    /**
     * @param HttpClient $client
     * @return mixed
     */
    public function setHttpClient(HttpClient $client)
    {
        return $this->client->setHttpClient($client);
    }

    /**
     * @return Serializer
     */
    public function getSerializer()
    {
        return $this->client->getSerializer();
    }

    /**
     * @return string
     */
    public function getApiUrl()
    {
        return $this->client->getApiUrl();
    }

}