# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import errno
import os
import pickle
import threading
import zlib

from libs.cache import Cache

ROOT_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir)
CACHE_DIR = os.path.join(ROOT_DIR, '.local_scripts', 'cache')


class LocalCache(Cache):
  """Cacher that uses local files to cache data."""
  lock = threading.Lock()

  def __init__(self, cache_dir=None):
    self._cache_dir = cache_dir
    self._initialized = False

  @property
  def cache_dir(self):
    return self._cache_dir or CACHE_DIR

  def Get(self, key):
    with LocalCache.lock:
      path = os.path.join(self.cache_dir, key)
      if not os.path.exists(path):
        return None

      try:
        with open(path) as f:
          return pickle.loads(zlib.decompress(f.read()))
      except Exception as error:  # pragma: no cover.
        raise Exception('Failed loading cache: %s' % error)

  def Set(self, key, data, expire_time=0):  # pylint: disable=W
    with LocalCache.lock:
      try:
        if not self._initialized:  # pragma: no cover.
          try:
            os.makedirs(self.cache_dir)
          except OSError as exc:
            if exc.errno != errno.EEXIST:
              raise
          self._initialized = True
        with open(os.path.join(self.cache_dir, key), 'wb') as f:
          f.write(zlib.compress(pickle.dumps(data)))
      except Exception as e:  # pragma: no cover.
        raise Exception('Failed setting cache for key %s: %s' % (key, e))
