import pickle  #  cPickle as pickle
from django.conf import settings
from django.utils import timezone

import redis

from threepio import logger

from api import get_esh_driver

from service.driver import get_admin_driver

admin_drivers = {}
drivers = {}


def _get_cached_admin_driver(provider, force=False):
    if not admin_drivers.get(provider) or force:
        admin_drivers[provider] = get_admin_driver(provider)
    return admin_drivers[provider]


def _get_cached_driver(provider=None, identity=None, force=False):
    if provider:
        return _get_cached_admin_driver(provider, force)
    if not drivers.get(identity) or force:
        drivers[identity] = get_esh_driver(identity)
    return drivers[identity]


def _get_cached(key, data_method, scrub_method):
    r = redis.StrictRedis()
    data = r.get(key)
    if not data:
        data = data_method()
        scrub_method(data)
        logger.debug("Updated redis({0}) using {1} and {2}".format(key, data_method, scrub_method))
        r.set(key, pickle.dumps(data))
        r.expire(key, 30)
        return data
    logger.debug("Actual type {0}".format(type(data)))
    return pickle.loads(data)


def _scrub(objects):
    for o in objects:
        o._connection = None
        for a in ["_node", "_volume", "_image"]:
            if hasattr(o, a):
                o.__dict__[a] = None
        if hasattr(o, "size") and hasattr(o.size, "_size"):
            if o.size._size:
                o.size._size = None


def _validate_parameters(provider, identity):
    if provider and identity:
        raise Exception("Use either provider or identity but not both.")


def get_cached_driver(provider=None, identity=None, force=False):
    _validate_parameters(provider, identity)
    return _get_cached_driver(provider=provider,
                              identity=identity,
                              force=force)


def get_cached_instances(provider=None, identity=None):
    _validate_parameters(provider, identity)
    cached_driver = _get_cached_driver(provider=provider, identity=identity)
    all_instances_method = cached_driver.list_all_instances
    if provider:
        key = "instances"
    else:
        key = "instances.{0}.{1}".format(identity.created_by.username, identity.id)
    return _get_cached(key,
                      all_instances_method,
                      _scrub)


def get_cached_volumes(provider=None, identity=None):
    _validate_parameters(provider, identity)
    cached_driver = _get_cached_driver(provider=provider, identity=identity)
    all_volumes_method = cached_driver.list_all_volumes
    if provider:
        key = "volumes"
    else:
        key = "volumes.{0}.{1}".format(identity.created_by.username, identity.id)
    return _get_cached(key,
                      all_volumes_method,
                      _scrub)


def get_cached_machines(provider=None, identity=None):
    _validate_parameters(provider, identity)
    cached_driver = _get_cached_driver(provider=provider, identity=identity)
    all_machines_method = cached_driver.list_machines
    if provider:
        key = "machines"
    else:
        key = "machines.{0}.{1}".format(identity.created_by.username, identity.id)
    return _get_cached(key,
                       all_machines_method,
                       _scrub)

@@ -765,16 +765,29 @@
 b_method
+, force=False
 ):%0A    r
@@ -809,16 +809,52 @@
 Redis()%0A
+    if force:%0A        r.delete(key)%0A
     data
@@ -1977,32 +1977,45 @@
 e, identity=None
+, force=False
 ):%0A    _validate
@@ -2113,32 +2113,84 @@
 dentity=identity
+,%0A                                       force=force
 )%0A    all_instan
@@ -2276,17 +2276,41 @@
 nstances
-%22
+.%7B0%7D%22.format(provider.id)
 %0A    els
@@ -2442,24 +2442,25 @@
             
+ 
 all_instance
@@ -2483,38 +2483,75 @@
                 
+ 
 _scrub
+,%0A                       force=force
 )%0A%0A%0Adef get_cach
@@ -2581,32 +2581,45 @@
 e, identity=None
+, force=False
 ):%0A    _validate
@@ -2717,32 +2717,84 @@
 dentity=identity
+,%0A                                       force=force
 )%0A    all_volume
@@ -2874,17 +2874,41 @@
 %22volumes
-%22
+.%7B0%7D%22.format(provider.id)
 %0A    els
@@ -3038,24 +3038,25 @@
             
+ 
 all_volumes_
@@ -3085,22 +3085,59 @@
         
+ 
 _scrub
+,%0A                       force=force
 )%0A%0A%0Adef 
@@ -3184,16 +3184,29 @@
 ity=None
+, force=False
 ):%0A    _
@@ -3316,24 +3316,76 @@
 ity=identity
+,%0A                                       force=force
 )%0A    all_ma
@@ -3468,17 +3468,41 @@
 machines
-%22
+.%7B0%7D%22.format(provider.id)
 %0A    els
@@ -3688,10 +3688,46 @@
   _scrub
+,%0A                       force=force
 )%0A

Add force parameter to get_cached_* methods in service.cache. modified: service/cache.py