<?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Mail\Header\Exception;

use 
Zend\Mail\Exception;

class 
BadMethodCallException extends Exception\BadMethodCallException implements
    
ExceptionInterface
{
}
    
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;
        
$ttl         $options->getTtl();

        if (!
wincache_ucache_add($internalKey$value$ttl)) {
            
$type is_object($value) ? get_class($value) : gettype($value);
            throw new 
Exception\RuntimeException(
                
"wincache_ucache_add('{$internalKey}', <{$type}>, {$ttl}) failed"
            
);
        }

        return 
true;
    }

    
/**
     * Internal method to add multiple items.
     *
     * @param  array $normalizedKeyValuePairs
     * @return array Array of not stored keys
     * @throws Exception\ExceptionInterface
     */
    
protected function internalAddItems(array & $normalizedKeyValuePairs)
    {
        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        if (
$namespace === '') {
            return 
wincache_ucache_add($normalizedKeyValuePairsnull$options->getTtl());
        }

        
$prefix                $namespace $options->getNamespaceSeparator();
        
$internalKeyValuePairs = array();
        foreach (
$normalizedKeyValuePairs as $normalizedKey => $value) {
            
$internalKey $prefix $normalizedKey;
            
$internalKeyValuePairs[$internalKey] = $value;
        }

        
$result wincache_ucache_add($internalKeyValuePairsnull$options->getTtl());

        
// remove key prefic
        
$prefixL strlen($prefix);
        foreach (
$result as & $key) {
            
$key substr($key$prefixL);
        }

        return 
$result;
    }

    
/**
     * Internal method to replace an existing item.
     *
     * @param  string $normalizedKey
     * @param  mixed  $value
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    
protected function internalReplaceItem(& $normalizedKey, & $value)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;
        if (!
wincache_ucache_exists($internalKey)) {
            return 
false;
        }

        
$ttl $options->getTtl();
        if (!
wincache_ucache_set($internalKey$value$ttl)) {
            
$type is_object($value) ? get_class($value) : gettype($value);
            throw new 
Exception\RuntimeException(
                
"wincache_ucache_set('{$internalKey}', <{$type}>, {$ttl}) failed"
            
);
        }

        return 
true;
    }

    
/**
     * Internal method to remove an item.
     *
     * @param  string $normalizedKey
     * @return bool
     * @throws Exception\ExceptionInterface
     */
    
protected function internalRemoveItem(& $normalizedKey)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;
        return 
wincache_ucache_delete($internalKey);
    }

    
/**
     * Internal method to remove multiple items.
     *
     * @param  array $normalizedKeys
     * @return array Array of not removed keys
     * @throws Exception\ExceptionInterface
     */
    
protected function internalRemoveItems(array & $normalizedKeys)
    {
        
$options   $this->getOptions();
        
$namespace $options->getNamespace();
        if (
$namespace === '') {
            
$result wincache_ucache_delete($normalizedKeys);
            return (
$result === false) ? $normalizedKeys $result;
        }

        
$prefix       $namespace $options->getNamespaceSeparator();
        
$internalKeys = array();
        foreach (
$normalizedKeys as $normalizedKey) {
            
$internalKeys[] = $prefix $normalizedKey;
        }

        
$result wincache_ucache_delete($internalKeys);
        if (
$result === false) {
            return 
$normalizedKeys;
        } elseif (
$result) {
            
// remove key prefix
            
$prefixL strlen($prefix);
            foreach (
$result as & $key) {
                
$key substr($key$prefixL);
            }
        }

        return 
$result;
    }

    
/**
     * Internal method to increment an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    
protected function internalIncrementItem(& $normalizedKey, & $value)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;
        return 
wincache_ucache_inc($internalKey, (int) $value);
    }

    
/**
     * Internal method to decrement an item.
     *
     * @param  string $normalizedKey
     * @param  int    $value
     * @return int|bool The new value on success, false on failure
     * @throws Exception\ExceptionInterface
     */
    
protected function internalDecrementItem(& $normalizedKey, & $value)
    {
        
$options     $this->getOptions();
        
$namespace   $options->getNamespace();
        
$prefix      = ($namespace === '') ? '' $namespace $options->getNamespaceSeparator();
        
$internalKey $prefix $normalizedKey;
        return 
wincache_ucache_dec($internalKey, (int) $value);
    }

    
/* status */

    /**
     * Internal method to get capabilities of this adapter
     *
     * @return Capabilities
     */
    
protected function internalGetCapabilities()
    {
        if (
$this->capabilities === null) {
            
$marker       = new stdClass();
            
$capabilities = new Capabilities(
                
$this,
                
$marker,
                array(
                    
'supportedDatatypes' => array(
                        
'NULL'     => true,
                        
'boolean'  => true,
                        
'integer'  => true,
                        
'double'   => true,
                        
'string'   => true,
                        
'array'    => true,
                        
'object'   => 'object',
                        
'resource' => false,
                    ),
                    
'supportedMetadata' => array(
                        
'internal_key''ttl''hits''size'
                    
),
                    
'minTtl'             => 1,
                    
'maxTtl'             => 0,
                    
'staticTtl'          => true,
                    
'ttlPrecision'       => 1,
                    
'useRequestTime'     => false,
                    
'expiredRead'        => false,
                    
'namespaceIsPrefix'  => true,
                    
'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
                )
            );

            
// update namespace separator on change option
            
$this->getEventManager()->attach('option', function ($event) use ($capabilities$marker) {
                
$params $event->getParams();

                if (isset(
$params['namespace_separator'])) {
                    
$capabilities->setNamespaceSeparator($marker$params['namespace_separator']);
                }
            });

            
$this->capabilities     $capabilities;
            
$this->capabilityMarker $marker;
        }

        return 
$this->capabilities;
    }

    
/* internal */

    /**
     * Normalize metadata to work with WinCache
     *
     * @param  array $metadata
     * @return void
     */
    
protected function normalizeMetadata(array & $metadata)
    {
        
$metadata['internal_key'] = $metadata['key_name'];
        
$metadata['hits']         = $metadata['hitcount'];
        
$metadata['ttl']          = $metadata['ttl_seconds'];
        
$metadata['size']         = $metadata['value_size'];

        unset(
            
$metadata['key_name'],
            
$metadata['hitcount'],
            
$metadata['ttl_seconds'],
            
$metadata['value_size']
        );
    }
}