# Copyright 2013 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.

from appengine_wrappers import GetAppVersion
from cache_chain_object_store import CacheChainObjectStore
from memcache_object_store import MemcacheObjectStore
from test_object_store import TestObjectStore
from persistent_object_store import PersistentObjectStore

_unspecified = object()

class ObjectStoreCreator(object):
  '''Creates ObjectStores with a namespacing and behaviour configuration.

  The initial configuration is specified on object store construction. When
  creating ObjectStores via Create this configuration can be overridden (or
  via the variants of Create which do this automatically).
  '''
  def __init__(self,
               # TODO(kalman): rename start_dirty?
               start_empty=_unspecified,
               # Override for testing. A custom ObjectStore type to construct
               # on Create(). Useful with TestObjectStore, for example.
               store_type=None,
               # Override for testing. Whether the ObjectStore type specified
               # with |store_type| should be wrapped e.g. with Caching. This is
               # useful to override when specific state tests/manipulations are
               # being done on the underlying object store.
               disable_wrappers=False):
    if start_empty is _unspecified:
      raise ValueError('start_empty must be specified (typically False)')
    self._start_empty = start_empty
    self._store_type = store_type
    if disable_wrappers and store_type is None:
      raise ValueError('disable_wrappers much specify a store_type')
    self._disable_wrappers = disable_wrappers

  @staticmethod
  def ForTest(start_empty=False,
              store_type=TestObjectStore,
              disable_wrappers=True):
    return ObjectStoreCreator(start_empty=start_empty,
                              store_type=store_type,
                              disable_wrappers=disable_wrappers)

  def Create(self,
             cls,
             category=None,
             # Override any of these for a custom configuration.
             start_empty=_unspecified,
             app_version=_unspecified):
    # Resolve namespace components.
    if start_empty is not _unspecified:
      start_empty = bool(start_empty)
    else:
      start_empty = self._start_empty
    if app_version is _unspecified:
      app_version = GetAppVersion()

    # Reserve & and = for namespace separators.
    for component in (category, app_version):
      if component and ('&' in component or '=' in component):
        raise ValueError('%s cannot be used in a namespace')

    namespace = '&'.join(
        '%s=%s' % (key, value)
        for key, value in (('class', cls.__name__),
                           ('category', category),
                           ('app_version', app_version))
        if value is not None)

    if self._disable_wrappers:
      return self._store_type(namespace, start_empty=start_empty)

    if self._store_type is not None:
      chain = (self._store_type(namespace),)
    else:
      chain = (MemcacheObjectStore(namespace), PersistentObjectStore(namespace))
    return CacheChainObjectStore(chain, start_empty=start_empty)
