<?php
/*
 * Copyright (c) 2023. RTM Business
 */

namespace WordpressModels\Cache;

use ErrorException;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Adapter\MemcachedAdapter;
use Symfony\Component\Cache\Adapter\NullAdapter;
use Symfony\Component\Cache\Adapter\TagAwareAdapter;
use Symfony\Component\Cache\Exception\CacheException;

class CacheFactory
{

    public function __construct(private string $namespace)
    {
    }

    public function createRouteCache(string $directory): FilesystemAdapter
    {
        return new FilesystemAdapter($this->namespace, directory: $directory);
    }

    /**
     * @throws ErrorException
     * @throws CacheException
     */
    public function createCache(?string $directory = null, string $prefix = '', array $memcachedOptions = []): AdapterInterface|TagAwareAdapter
    {
        $directory ??= get_temp_dir() . '/cache';
        $defaultAdapter = new FilesystemAdapter($this->namespace, directory: $directory);

        $canUseMemcached = MemcachedAdapter::isSupported() && defined('MEMCACHED_DSN') && MEMCACHED_DSN;
        if ($canUseMemcached) {
            $memcached = MemcachedAdapter::createConnection(MEMCACHED_DSN, $memcachedOptions);

            if (empty($memcached->getStats())) {
                return $defaultAdapter;
            }

            $adapter = new MemcachedAdapter($memcached, $this->namespace);
        } elseif (ApcuAdapter::isSupported()) {
            $adapter = new ApcuAdapter($this->namespace);
        } elseif (is_writable($directory)) {
            $adapter = new FilesystemAdapter($this->namespace, directory: $directory);
        } else {
            return new NullAdapter();
        }

        // create a tag-aware adapter from the memcached adapter, if supported
        if ($canUseMemcached) {
            $tagConnection = MemcachedAdapter::createConnection(MEMCACHED_DSN, $memcachedOptions);

            return new TagAwareAdapter($adapter, new MemcachedAdapter($tagConnection, "{$this->namespace}_tags_"));
        }

        return $adapter;
    }

}
