# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed 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.

"""File based cache for the discovery document.

The cache is stored in a single file so that multiple processes can
share the same cache. It locks the file whenever accesing to the
file. When the cache content is corrupted, it will be initialized with
an empty cache.
"""

from __future__ import division

import datetime
import json
import logging
import os
import tempfile
import threading

try:
  from oauth2client.contrib.locked_file import LockedFile
except ImportError:
  # oauth2client < 2.0.0
  from oauth2client.locked_file import LockedFile

from . import base
from ..discovery_cache import DISCOVERY_DOC_MAX_AGE

LOGGER = logging.getLogger(__name__)

FILENAME = 'google-api-python-client-discovery-doc.cache'
EPOCH = datetime.datetime.utcfromtimestamp(0)


def _to_timestamp(date):
  try:
    return (date - EPOCH).total_seconds()
  except AttributeError:
    # The following is the equivalent of total_seconds() in Python2.6.
    # See also: https://docs.python.org/2/library/datetime.html
    delta = date - EPOCH
    return ((delta.microseconds + (delta.seconds + delta.days * 24 * 3600)
             * 10**6) / 10**6)


def _read_or_initialize_cache(f):
  f.file_handle().seek(0)
  try:
    cache = json.load(f.file_handle())
  except Exception:
    # This means it opens the file for the first time, or the cache is
    # corrupted, so initializing the file with an empty dict.
    cache = {}
    f.file_handle().truncate(0)
    f.file_handle().seek(0)
    json.dump(cache, f.file_handle())
  return cache


class Cache(base.Cache):
  """A file based cache for the discovery documents."""

  def __init__(self, max_age):
      """Constructor.

      Args:
        max_age: Cache expiration in seconds.
      """
      self._max_age = max_age
      self._file = os.path.join(tempfile.gettempdir(), FILENAME)
      f = LockedFile(self._file, 'a+', 'r')
      try:
        f.open_and_lock()
        if f.is_locked():
          _read_or_initialize_cache(f)
        # If we can not obtain the lock, other process or thread must
        # have initialized the file.
      except Exception as e:
        LOGGER.warning(e, exc_info=True)
      finally:
        f.unlock_and_close()

  def get(self, url):
    f = LockedFile(self._file, 'r+', 'r')
    try:
      f.open_and_lock()
      if f.is_locked():
        cache = _read_or_initialize_cache(f)
        if url in cache:
          content, t = cache.get(url, (None, 0))
          if _to_timestamp(datetime.datetime.now()) < t + self._max_age:
            return content
        return None
      else:
        LOGGER.debug('Could not obtain a lock for the cache file.')
        return None
    except Exception as e:
      LOGGER.warning(e, exc_info=True)
    finally:
      f.unlock_and_close()

  def set(self, url, content):
    f = LockedFile(self._file, 'r+', 'r')
    try:
      f.open_and_lock()
      if f.is_locked():
        cache = _read_or_initialize_cache(f)
        cache[url] = (content, _to_timestamp(datetime.datetime.now()))
        # Remove stale cache.
        for k, (_, timestamp) in list(cache.items()):
          if _to_timestamp(datetime.datetime.now()) >= timestamp + self._max_age:
            del cache[k]
        f.file_handle().truncate(0)
        f.file_handle().seek(0)
        json.dump(cache, f.file_handle())
      else:
        LOGGER.debug('Could not obtain a lock for the cache file.')
    except Exception as e:
      LOGGER.warning(e, exc_info=True)
    finally:
      f.unlock_and_close()


cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)
