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

"""A mutable tree implementation that is backed by Datastore."""




from . import common

from google.appengine.ext import ndb

# The total entity size is 1048572 (1MB - 4), and having some margin below it.
MAX_BYTES_FOR_ENTITY = 921600  # 900 kbytes


def _SplitByLength(seq, length):
  """A helper function for spliting a string or blob into sized chunks."""
  return [seq[i:i+length] for i in range(0, len(seq), length)]


# TODO: Unfortunately this model will pollute the target application's
# Datastore.  The name (prefixed with _Ah) was chosen to minimize collision,
# but there may be a better mechanism.
class _AhMimicFile(ndb.Model):
  """A Model to store file contents in Datastore.

  The file's path should be used as the key for the entity.
  """
  contents = ndb.BlobProperty()
  chunk_keys = ndb.KeyProperty(repeated=True, indexed=False)
  updated = ndb.DateTimeProperty(auto_now=True, indexed=False)

  def GetContents(self):
    if self.chunk_keys:
      chunk_list = ndb.get_multi(self.chunk_keys)
      contents_list = [chunk.contents for chunk in chunk_list]
      return ''.join(contents_list)
    else:
      return self.contents


class _AhMimicChunk(ndb.Model):
  """A Model to store a chunk of file contents.

  All of the siblings should have one single _AhMimicFile entity as a parent.
  """
  contents = ndb.BlobProperty()


class DatastoreTree(common.Tree):
  """An implementation of Tree backed by Datastore."""

  # pylint:disable-msg=unused-argument
  def __init__(self, namespace='', access_key=None):
    super(DatastoreTree, self).__init__(namespace, access_key)
    # Having a root entity key allows us to use ancestor queries for strong
    # consistency in the High Replication Datastore
    assert namespace is not None