from __future__ import absolute_import, print_function, division
import logging
import six.moves.cPickle as pickle

_logger = logging.getLogger("theano.gof.callcache")


class CallCache(object):
    def __init__(self, filename=None):
        self.filename = filename
        try:
            if filename is None:
                raise IOError('bad filename')  # just goes to except
            with open(filename, 'r') as f:
                self.cache = pickle.load(f)
        except IOError:
            self.cache = {}

    def persist(self, filename=None):
        """
        Cache "filename" as a pickle file
        """
        if filename is None:
            filename = self.filename
        with open(filename, 'w') as f:
            pickle.dump(self.cache, f)

    def call(self, fn, args=(), key=None):
        """
        Retrieve item from the cache(if available)
        based on a key

        Parameters:
        ----------
        key
            parameter to retrieve cache item
        fn,args
            key to retrieve if "key" is None
        """
        if key is None:
            key = (fn, tuple(args))
        if key not in self.cache:
            _logger.debug('cache miss %i', len(self.cache))
            self.cache[key] = fn(*args)
        else:
            _logger.debug('cache hit %i', len(self.cache))
        return self.cache[key]

    def __del__(self):
        try:
            if self.filename:
                self.persist()
        except Exception as e:
            _logger.error('persist failed %s %s', self.filename, e)
