from google.appengine.ext import db
import logging
from orangescape.model.server.util.listutil import split_seq

def split_data(data):
    splitSize = (1024*1024)-500
    return split_seq(data, splitSize)

def merge_data(dataSeq):
    return ''.join(dataSeq)

class AbsBlobEntity(db.Model):
    __content = None
    contentLoaded = False

    def save_all_parts(self):
        db.put(self)
        existingParts = self.blobParts
        dataParts = split_data(self.__content) if self.__content else []
#        logging.info('Data splitted into %s parts'%(len(dataParts)))
        i = 0
        blobParts = []
        existingPartsSize = existingParts.count()
        for part in dataParts:
            if i < existingPartsSize:
#                logging.debug('Updating existing part %s with the new part %s'%(existingParts[i].partNo, i+1))
                blobPart = existingParts[i]
            else:
                blobPart = BlobPart()
                blobPart.blobEntity = self
            blobPart.content = part
            blobPart.partNo = i+1
            blobParts.append(blobPart)
            blobPart.put()
            i+=1

        while i < existingPartsSize:
#            logging.debug('Deleting part %s %s'%(existingParts[existingParts.count()-1].partNo, i))
            existingParts[existingParts.count()-1].delete()
            i+=1

    def put(self):
        """*****Migrating the old attachment implementation**************"""
        if hasattr(self, 'file'):
            f = getattr(self, 'file')
            if f:
                setattr(self, 'file', None)
        """**************************************************************"""

        self.save_all_parts()
#        db.run_in_transaction(self.save_all_parts)

    def delete(self):
        db.delete(self.blobParts)
        db.delete(self)

    def setContent(self, content):
        self.__content = content
        self.contentLoaded = True

    def getContent(self):
        """*****For backward compatability******************************"""
        if hasattr(self, 'file'):
            f = getattr(self, 'file')
            if f:
                return f
        """*************************************************************"""

        if not self.contentLoaded:
            self.contentLoaded = True
            blobParts = [part for part in self.blobParts]
            blobParts.sort(lambda x, y:cmp(x.partNo, y.partNo))
            self.__content = merge_data([part.content for part in blobParts])
        return self.__content

    content = property(getContent, setContent)

class BlobPart(db.Model):
    blobEntity = db.ReferenceProperty(AbsBlobEntity, collection_name="blobParts")
    content = db.BlobProperty(default=None)
    partNo = db.IntegerProperty()

class Attachment(AbsBlobEntity):
    instanceId = db.StringProperty()
    file = db.BlobProperty(default=None)

class AttachmentVersion(AbsBlobEntity):
    attachment = db.ReferenceProperty(Attachment, collection_name="attachmentVersionList")
    file = db.BlobProperty(default=None)
    versionedBy = db.StringProperty()
    versionedAt = db.DateTimeProperty()
    comments = db.StringProperty()

    def getAttachmentVersion(self):
        return self.attachment

    def getVersionedBy(self):
        return self.versionedBy

    def getVersionedAt(self):
        return self.versionedAt
