<?php
namespace Fifa\ConnectServiceBus\Sdk\Encryption;

use Fifa\ConnectServiceBus\Sdk\Authentication\CacheStorageInterface;
use Fifa\ConnectServiceBus\Sdk\Encryption\Model\CacheItem;
use Fifa\ConnectServiceBus\Sdk\Encryption\Model\PublicCertificate;
use Fifa\ConnectServiceBus\Sdk\Utils\SerializableCache;

/**
 * Class CertificateCache
 * @package Fifa\ConnectServiceBus\Sdk\Encryption
 */
class CertificateCache implements CertificateCacheInterface
{
    /**
     * @var SerializableCache
     */
    private $serializableCache;

    /**
     * @var CacheItem[]
     */
    private $inMemoryCacheItems;

    /**
     * Constructor
     *
     * @param CacheStorageInterface $cacheStorage
     * @param int $expirationTimeSpanInSeconds - for how long item in cache should be valid until it's deleted, in seconds
     */
    public function __construct(CacheStorageInterface $cacheStorage, int $expirationTimeSpanInSeconds)
    {
        $this->serializableCache = new SerializableCache($cacheStorage);
        $this->serializableCache->setExpirationTimeSpanInSeconds($expirationTimeSpanInSeconds);
    }

    /**
     * @inheritDoc
     */
    public function getCertificateFromCache(string $queueIdentifier): ?PublicCertificate
    {
        if (!$this->isValid($queueIdentifier)) {
            return null;
        }

        return $this->inMemoryCacheItems[$queueIdentifier]->getData();
    }

    /**
     * @inheritDoc
     */
    public function storeCache(PublicCertificate $certificate)
    {
        $cacheItem = new CacheItem($certificate, time() + $this->serializableCache->getExpirationTimeSpanInSeconds());
        $this->serializableCache->put($certificate->getQueueIdentifier(), $cacheItem);
        $this->inMemoryCacheItems[$certificate->getQueueIdentifier()] = $cacheItem;
    }

    /**
     * Checks whether stored cache is still valid
     *
     * @param string $queueIdentifier
     * @return bool
     */
    private function isValid(string $queueIdentifier): bool
    {
        if (!isset($this->inMemoryCacheItems[$queueIdentifier]) || !$this->inMemoryCacheItems[$queueIdentifier]) {
            $certificate = $this->serializableCache->get($queueIdentifier);
            if(isset($certificate) && $certificate) {
                $this->inMemoryCacheItems[$queueIdentifier] = $certificate;
            } else {
                return false;
            }
        }

        $diff = $this->inMemoryCacheItems[$queueIdentifier]->getExpiresOn() - time();

        return $diff > 0;
    }
}