<?php

/**
 * @see       https://github.com/laminas/laminas-cache for the canonical source repository
 * @copyright https://github.com/laminas/laminas-cache/blob/master/COPYRIGHT.md
 * @license   https://github.com/laminas/laminas-cache/blob/master/LICENSE.md New BSD License
 */

namespace Laminas\Cache\Storage\Adapter;

use ArrayAccess;
use Laminas\Cache\Exception;

use function sprintf;
use function strlen;

/**
 * These are options specific to the Memcache adapter
 */
class MemcacheOptions extends AdapterOptions
{
    // @codingStandardsIgnoreStart
    /**
     * Prioritized properties ordered by prio to be set first
     * in case a bulk of options sets set at once
     *
     * @var string[]
     */
    protected $__prioritizedProperties__ = ['resource_manager', 'resource_id'];
    // @codingStandardsIgnoreEnd

    /**
     * The namespace separator
     *
     * @var string
     */
    protected $namespaceSeparator = ':';

    /**
     * The memcache resource manager
     *
     * @var null|MemcacheResourceManager
     */
    protected $resourceManager;

    /**
     * The resource id of the resource manager
     *
     * @var string
     */
    protected $resourceId = 'default';

    /**
     * Enable compression when data is written
     *
     * @var bool
     */
    protected $compression = false;

    /**
     * Set namespace.
     *
     * @param string $namespace
     * @return MemcacheOptions
     */
    public function setNamespace($namespace)
    {
        $namespace = (string) $namespace;

        if (128 < strlen($namespace)) {
            throw new Exception\InvalidArgumentException(sprintf(
                '%s expects a prefix key of no longer than 128 characters',
                __METHOD__
            ));
        }

        return parent::setNamespace($namespace);
    }

    /**
     * Set namespace separator
     *
     * @param  string $namespaceSeparator
     * @return MemcacheOptions
     */
    public function setNamespaceSeparator($namespaceSeparator)
    {
        $namespaceSeparator = (string) $namespaceSeparator;
        if ($this->namespaceSeparator !== $namespaceSeparator) {
            $this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
            $this->namespaceSeparator = $namespaceSeparator;
        }
        return $this;
    }

    /**
     * Get namespace separator
     *
     * @return string
     */
    public function getNamespaceSeparator()
    {
        return $this->namespaceSeparator;
    }

    /**
     * Set the memcache resource manager to use
     *
     * @return MemcacheOptions
     */
    public function setResourceManager(?MemcacheResourceManager $resourceManager = null)
    {
        if ($this->resourceManager !== $resourceManager) {
            $this->triggerOptionEvent('resource_manager', $resourceManager);
            $this->resourceManager = $resourceManager;
        }
        return $this;
    }

    /**
     * Get the memcache resource manager
     *
     * @return MemcacheResourceManager
     */
    public function getResourceManager()
    {
        if (! $this->resourceManager) {
            $this->resourceManager = new MemcacheResourceManager();
        }
        return $this->resourceManager;
    }

    /**
     * Get the memcache resource id
     *
     * @return string
     */
    public function getResourceId()
    {
        return $this->resourceId;
    }

    /**
     * Set the memcache resource id
     *
     * @param string $resourceId
     * @return MemcacheOptions
     */
    public function setResourceId($resourceId)
    {
        $resourceId = (string) $resourceId;
        if ($this->resourceId !== $resourceId) {
            $this->triggerOptionEvent('resource_id', $resourceId);
            $this->resourceId = $resourceId;
        }
        return $this;
    }

    /**
     * Is compressed writes turned on?
     *
     * @return boolean
     */
    public function getCompression()
    {
        return $this->compression;
    }

    /**
     * Set whether compressed writes are turned on or not
     *
     * @param boolean $compression
     * @return $this
     */
    public function setCompression($compression)
    {
        $compression = (bool) $compression;
        if ($this->compression !== $compression) {
            $this->triggerOptionEvent('compression', $compression);
            $this->compression = $compression;
        }
        return $this;
    }

    /**
     * Sets a list of memcache servers to add on initialize
     *
     * @param string|array $servers list of servers
     * @return MemcacheOptions
     * @throws Exception\InvalidArgumentException
     */
    public function setServers($servers)
    {
        $this->getResourceManager()->addServers($this->getResourceId(), $servers);
        return $this;
    }

    /**
     * Get Servers
     *
     * @return array
     */
    public function getServers()
    {
        return $this->getResourceManager()->getServers($this->getResourceId());
    }

    /**
     * Set compress threshold
     *
     * @param int|string|array|ArrayAccess|null $threshold
     * @return MemcacheOptions
     */
    public function setAutoCompressThreshold($threshold)
    {
        $this->getResourceManager()->setAutoCompressThreshold($this->getResourceId(), $threshold);
        return $this;
    }

    /**
     * Get compress threshold
     *
     * @return int|null
     */
    public function getAutoCompressThreshold()
    {
        return $this->getResourceManager()->getAutoCompressThreshold($this->getResourceId());
    }

    /**
     * Set compress min savings option
     *
     * @param  float|string|null $minSavings
     * @return MemcacheOptions
     */
    public function setAutoCompressMinSavings($minSavings)
    {
        $this->getResourceManager()->setAutoCompressMinSavings($this->getResourceId(), $minSavings);
        return $this;
    }

    /**
     * Get compress min savings
     *
     * @throws Exception\RuntimeException
     * @return float|null
     */
    public function getAutoCompressMinSavings()
    {
        return $this->getResourceManager()->getAutoCompressMinSavings($this->getResourceId());
    }

    /**
     * Set default server values
     *
     * @param array $serverDefaults
     * @return MemcacheOptions
     */
    public function setServerDefaults(array $serverDefaults)
    {
        $this->getResourceManager()->setServerDefaults($this->getResourceId(), $serverDefaults);
        return $this;
    }

    /**
     * Get default server values
     *
     * @return array
     */
    public function getServerDefaults()
    {
        return $this->getResourceManager()->getServerDefaults($this->getResourceId());
    }

    /**
     * Set callback for server connection failures
     *
     * @param callable $callback
     * @return $this
     */
    public function setFailureCallback($callback)
    {
        $this->getResourceManager()->setFailureCallback($this->getResourceId(), $callback);
        return $this;
    }

    /**
     * Get callback for server connection failures
     *
     * @return callable
     */
    public function getFailureCallback()
    {
        return $this->getResourceManager()->getFailureCallback($this->getResourceId());
    }
}
