from dogpile.cache.backends.memory import MemoryBackend
import dogpile.cache.backends.memcached
import dogpile.cache.exception
import pytest

from pyramid_dogpile_cache2 import configure_dogpile_cache, get_region


def test_sets_backend_for_regions(empty_config):
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo, bar',
            'dogpile_cache.backend': 'dogpile.cache.memory',
            'dogpile_cache.expiration_time': '1',
        }
    )
    assert isinstance(get_region('foo').backend, MemoryBackend)
    assert isinstance(get_region('bar').backend, MemoryBackend)


def test_converts_expiration_time(empty_config):
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.memory',
            'dogpile_cache.expiration_time': '1',
        }
    )
    assert get_region('foo').expiration_time == 1


def test_converts_expiration_time_to_int(empty_config):
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.memory',
            'dogpile_cache.expiration_time': '1',
        }
    )
    assert get_region('foo').expiration_time == 1


def test_sets_memcache_expire_time_to_later_than_expiration_time(empty_config, monkeypatch):
    monkeypatch.setattr(
        dogpile.cache.backends.memcached.PylibmcBackend, '_imports', lambda self: None
    )
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.pylibmc',
            'dogpile_cache.pylibmc_url': 'http://localhost:8899',
            'dogpile_cache.expiration_time': '1',
            'dogpile_cache.memcache_expire_time_interval': '5',
        }
    )
    assert get_region('foo').backend.set_arguments['time'] == 6


def test_sets_pylibmc_behaviours(empty_config, monkeypatch):
    monkeypatch.setattr(
        dogpile.cache.backends.memcached.PylibmcBackend, '_imports', lambda self: None
    )
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.pylibmc',
            'dogpile_cache.pylibmc_url': 'http://localhost:8899',
            'dogpile_cache.expiration_time': '1',
            'dogpile_cache.pylibmc_behavior.send_timeout': '5',
        }
    )
    assert get_region('foo').backend.behaviors == {'send_timeout': 5}


def test_unconfigured_region_raises(empty_config):
    get_region('bar')
    with pytest.raises(dogpile.cache.exception.RegionNotConfigured):
        configure_dogpile_cache(
            {
                'dogpile_cache.regions': 'foo',
                'dogpile_cache.backend': 'dogpile.cache.memory',
                'dogpile_cache.expiration_time': '1',
            }
        )


def test_multiple_calls_clear_backend(empty_config):
    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.memory',
            'dogpile_cache.expiration_time': '1',
        }
    )

    region = get_region('foo')

    # Init cached value in region
    _ = region.actual_backend

    original_backend = region.backend
    assert region.actual_backend == original_backend

    configure_dogpile_cache(
        {
            'dogpile_cache.regions': 'foo',
            'dogpile_cache.backend': 'dogpile.cache.memory',
            'dogpile_cache.expiration_time': '1',
        }
    )

    # Confirm region is back to fresh state
    new_backend = region.backend
    assert new_backend != original_backend
    assert region._actual_backend is None

    # Regen cached value. Confirm cache points to new backend
    _ = region.actual_backend
    assert region.actual_backend == new_backend
