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

use Fifa\ConnectServiceBus\Sdk\Utils\File;
use InvalidArgumentException;
use RuntimeException;

/**
 * Class CacheFileStorage
 * @package Fifa\ConnectServiceBus\Sdk\Authentication
 */
class CacheFileStorage implements CacheStorageInterface
{
    /**
     * @var string
     */
    private $filePath;

    /**
     * Cache constructor.
     * @param string|null $folderPath
     */
    public function __construct(?string $folderPath = null)
    {
        $defaultCacheFolder = str_replace('src' . DIRECTORY_SEPARATOR . 'Authentication', '', dirname(__FILE__)) . '.cache' . DIRECTORY_SEPARATOR;
        $this->setFilePath(is_string($folderPath) ? $folderPath : $defaultCacheFolder);
    }

    /**
     * Returns string representation of the object
     *
     * @return string
     */
    public function __toString()
    {
        return "FilePath: " . $this->getFilePath();
    }

    /**
     * Gets file path
     *
     * @return string
     */
    public function getFilePath(): string
    {
        return $this->filePath;
    }

    /**
     * Gets serialized data from cache file. Returns null in case when file doesn't exist;
     *
     * @param string $cacheId
     * @return string|null
     */
    public function get(string $cacheId): ?string
    {
        $data = null;
        $filename = $this->generateFilename($cacheId);
        if (file_exists($this->filePath . $filename)){
            $data = File::getContents($this->filePath . $filename);
        }

        return $data;
    }

    /**
     * Store given serialized object into cache file.
     *
     * @param string $cacheId
     * @param mixed $object
     */
    public function put($object, string $cacheId)
    {
        file_put_contents($this->filePath . $this->generateFilename($cacheId), $object);
    }

    /**
     * Generates and returns cache file name
     *
     * @param string $input
     * @return string
     */
    public function generateFilename(string $input): string
    {
        return md5(serialize($input)) . '.cache';
    }

    /**
     * Sets file path
     *
     * @param string $filePath
     * @return CacheStorageInterface
     *
     * @throws InvalidArgumentException
     * @throws RuntimeException
     */
    private function setFilePath(string $filePath): CacheStorageInterface
    {
        if (!file_exists($filePath)) {
            throw new InvalidArgumentException(sprintf('Given folder location doesn\'t exist: "%s"', $filePath));
        }

        if (!is_writable($filePath)) {
            throw new RuntimeException(sprintf('Folder "%s" is not writable.', $filePath));
        }

        $this->filePath = $filePath;
        return $this;
    }
}