# -*- coding: utf-8 -*-

# Copyright (c) 2013, Theo Crevon
# Copyright (c) 2013, Greg Leclercq
#
# See the file LICENSE for copying permission.

from datetime import datetime, timedelta
from time import mktime

from functools import wraps

# De-capitalize a string (lower first character)
decapitalize = lambda s: s[:1].lower() + s[1:] if s else ''

# Get a past day datetime
past_day = lambda d: datetime.now() - timedelta(days=d)

# Get a datetime timestamp
datetime_timestamp = lambda datetime: mktime(datetime.timetuple())


def enum(*sequential, **named):
    """Enums python implementation

    To be used like this :
        Numbers = enum('ZERO', 'ONE', 'TWO')
        >>> Numbers.ZERO
        0
        >>> Numbers.ONE
        1

    Found here: http://stackoverflow.com/questions/36932/whats-the-best-way-to-implement-an-enum-in-python
    """
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)


def get_subkey(d, key_path):
    """Gets a sub-dict key, and return None if whether
    the parent or child dict key does not exist

    Example:
    >>> d = {
      'a': {
        '1': 2,
        '2': 3,
      }
    }
    >>> subkey(d, ['a'])
    {'1': 2, '2': 3}
    >>> subkey(d, ['a', '1'])
    2
    >>> subkey(d, ['a', '3'])
    None

    :param  d: dict to operate over
    :type   d: dict of dicts

    :param  key_path: dict keys path list representation
    :type   key_path: list
    """
    if len(key_path) > 1:
        if d.get(key_path[0]) is None:
            return None
        return get_subkey(d[key_path[0]], key_path[1:])
    else:
        return d.get(key_path[0])


class _CachedProperty(property):
    """A property cache mechanism.

    The cache is stored on the model as a protected attribute. Expensive
    property lookups, such as database access, can therefore be sped up
    when accessed multiple times in the same request.

    The property can also be safely set and deleted without interference.
    """

    def __init__(self, fget, fset=None, fdel=None, doc=None):
        """Initializes the cached property."""
        self._cache_name = "_{name}_cache".format(
            name=fget.__name__,
        )
        # Wrap the accessors.
        fget = self._wrap_fget(fget)
        if callable(fset):
            fset = self._wrap_fset(fset)
        if callable(fdel):
            fdel = self._wrap_fdel(fdel)
        # Create the property.
        super(_CachedProperty, self).__init__(fget, fset, fdel, doc)

    def _wrap_fget(self, fget):
        @wraps(fget)
        def do_fget(obj):
            if hasattr(obj, self._cache_name):
                return getattr(obj, self._cache_name)
            # Generate the value to cache.
            value = fget(obj)
            setattr(obj, self._cache_name, value)
            return value
        return do_fget

    def _wrap_fset(self, fset):
        @wraps(fset)
        def do_fset(obj, value):
            fset(obj, value)
            setattr(obj, self._cache_name, value)
        return do_fset

    def _wrap_fdel(self, fdel):
        @wraps(fdel)
        def do_fdel(obj):
            fdel(obj)
            delattr(obj, self._cache_name)
        return do_fdel
cached_property = _CachedProperty


def immutable(mutableclass):
    """ Decorator for making a slot-based class immutable

    Source: http://code.activestate.com/recipes/578233-immutable-class-decorator/
    """

    if not isinstance(type(mutableclass), type):
        raise TypeError('@immutable: must be applied to a new-style class')
    if not hasattr(mutableclass, '__slots__'):
        raise TypeError('@immutable: class must have __slots__')

    class immutableclass(mutableclass):
        __slots__ = ()                      # No __dict__, please   

        def __new__(cls, *args, **kw):
            new = mutableclass(*args, **kw) # __init__ gets called while still mutable
            new.__class__ = immutableclass  # locked for writing now
            return new

        def __init__(self, *args, **kw):    # Prevent re-init after __new__
            pass

    # Copy class identity:
    immutableclass.__name__ = mutableclass.__name__
    immutableclass.__module__ = mutableclass.__module__

    # Make read-only:
    for name, member in mutableclass.__dict__.items():
        if hasattr(member, '__set__'):
            setattr(immutableclass, name, property(member.__get__))

    return immutableclass
@@ -526,37 +526,25 @@
 )%0A%0A%0A
-def enum(*sequential, **named
+class Enum(object
 ):%0A 
@@ -728,19 +728,126 @@
     
-Found here:
+    or%0A%0A        Numbers = enum(zero=%22ZERO%22, one=%22ONE%22)%0A        %3E%3E%3E Numbers.zero%0A        %22ZERO%22%0A%0A    Inspired from:%0A   
  htt
@@ -946,16 +946,71 @@
 %22%22%22%0A    
+def __init__(self, *sequential, **named):%0A        self.
 enums = 
@@ -1068,41 +1068,270 @@
 ed)%0A
-    return type('Enum', (), enums
+%0A        for key, value in self.enums.viewitems():%0A            setattr(self, key, value)%0A%0A    def __contains__(self, key):%0A        return key in self.enums%0A%0A    def has_member(self, member):%0A        return any(value == member for value in self.enums.itervalues()
 )%0A%0A%0A
@@ -4144,19 +4144,16 @@
 , please
-   
 %0A%0A      

enhance Enum util