# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Caching utilities.
"""

from __future__ import absolute_import  # so we can import standard 'collections' and 'threading'

from threading import Lock
from functools import partial

from .collections import OrderedDict


class cachedmethod(object):                                                                         # pylint: disable=invalid-name
    """
    Decorator for caching method return values.

    The implementation is thread-safe.

    Supports ``cache_info`` to be compatible with Python 3's ``functools.lru_cache``. Note that the
    statistics are combined for all instances of the class.

    Won't use the cache if not called when bound to an object, allowing you to override the cache.

    Adapted from `this solution
    <http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/>`__.
    """

    ENABLED = True

    def __init__(self, func):
        self.__doc__ = func.__doc__
        self.func = func
        self.hits = 0
        self.misses = 0
        self.lock = Lock()

    def cache_info(self):
        with self.lock:
            return (self.hits, self.misses, None, self.misses)

    def reset_cache_info(self):
        with self.lock:
            self.hits = 0
            self.misses = 0

    def __get__(self, instance, owner):
        if instance is None:
            # Don't use cache if not bound to an object
            # Note: This is also a way for callers to override the cache
            return self.func
        return partial(self, instance)

    def __call__(self, *args, **kwargs):
        if not self.ENABLED:
            return self.func(*args, **kwargs)

        instance = args[0]
        if not hasattr(instance, '_method_cache'):
            instance._method_cache = {}
        method_cache = instance._method_cache

        key = (self.func, args[1:], frozenset(kwargs.items()))

        try:
            with self.lock:
                return_value = method_cache[key]
                self.hits += 1
        except KeyError:
            return_value = self.func(*args, **kwargs)
            with self.lock:
                method_cache[key] = return_value
                self.misses += 1
            # Another thread may override our cache entry here, so we need to read
            # it again to make sure all threads use the same return value
            return_value = method_cache.get(key, return_value)

        return return_value


class HasCachedMethods(object):
    """
    Provides convenience methods for working with :class:`cachedmethod`.
    """

    def __init__(self, method_cache=None):
        self._method_cache = method_cache or {}

    @property
    def _method_cache_info(self):
        """
        The cache infos of all cached methods.

        :rtype: dict of str, 4-tuple
        """

        cached_info = OrderedDict()
        for k, v in self.__class__.__dict__.iteritems():
            if isinstance(v, property):
                # The property getter might be cached
                v = v.fget
            if hasattr(v, 'cache_info'):
                cached_info[k] = v.cache_info()
        return cached_info

    def _reset_method_cache(self):
        """
        Resets the caches of all cached methods.
        """

        if hasattr(self, '_method_cache'):
            self._method_cache = {}

        # Note: Another thread may already be storing entries in the cache here.
        # But it's not a big deal! It only means that our cache_info isn't
        # guaranteed to be accurate.

        for entry in self.__class__.__dict__.itervalues():
            if isinstance(entry, property):
                # The property getter might be cached
                entry = entry.fget
            if hasattr(entry, 'reset_cache_info'):
                entry.reset_cache_info()
