from orangescape.model.server.util.json import write_line
from cStringIO import StringIO
import logging

class SheetSerializer():
    def __init__(self, session, sheet, excludeListDict, dictionary=False):
        self.session = session
        self.sheet = sheet
        self.serializedRecords = {}
        self.excludeListDict = excludeListDict
        self.dictionary = dictionary

    def serialize_records(self, sObj, record):
        if not self.serializedRecords.has_key(record.getSheetId()):
            self.serializedRecords[record.getSheetId()] = record.getSheetId()
            if self.dictionary:
                sObj[record.getSheetId()] = record.getPrivateData()
            else:
                write_line(sObj, record.getSheetId(), record.getPrivateData())
            for referenceCell in record.getSheetMetadata().getOneToManyList():
                excludeList = self.excludeListDict.get(record.getSheetMetadata().getSheetId()) or []
                if referenceCell.isCascade() and not excludeList.__contains__(referenceCell.getSheetId()):
                    for child in self.session.getList(record, referenceCell):
                        self.serialize_records(sObj, child)

    def serializeSheet(self):
        if self.dictionary:
            sObj = {}
        else:
            sObj = StringIO()
            sObj.write('{')
        self.serialize_records(sObj, self.sheet)
        if self.dictionary:
            return sObj
        sObj.write('\n}')
        return sObj.getvalue()

    def serializeSubscription(self):
        appMetadata = self.session.getApplication().getSheetMetadata('Application')
        appInstance = self.session.get(self.sheet.getValue('Application'), appMetadata)
        if self.dictionary:
            sObj = {}
            sObj[self.sheet.getSheetId()] = self.sheet.getPrivateData()
            sObj[appInstance.getSheetId()] = appInstance.getPrivateData()
            themeId = appInstance.getValue('Themes')
            if themeId:
                theme = self.session.get(themeId, self.session.getApplication().getSheetMetadata('Themes'))
                sObj[theme.getSheetId()] = theme.getPrivateData()

        else:
            sObj = StringIO()
            sObj.write('{\n')
            write_line(sObj, self.sheet.getSheetId(), self.sheet.getPrivateData())
            write_line(sObj, appInstance.getSheetId(), appInstance.getPrivateData())

            themeId = appInstance.getValue('Themes')
            if themeId:
                theme = self.session.get(themeId, self.session.getApplication().getSheetMetadata('Themes'))
                write_line(sObj, theme.getSheetId(), theme.getPrivateData())

        for referenceCell in appMetadata.getOneToManyList():
            excludeList = self.excludeListDict.get(appMetadata.getSheetId()) or []
            if referenceCell.isCascade() and not excludeList.__contains__(referenceCell.getSheetId()):
                for child in self.session.getList(appInstance, referenceCell):
                    self.serialize_records(sObj, child)

        if self.dictionary:
            return sObj
        sObj.write('\n}')
        return sObj.getvalue()

    def serializeApplication(self):
        if self.dictionary:
            sObj = {}
            sObj[self.sheet.getSheetId()] = self.sheet.getPrivateData()
            themeId = self.sheet.getValue('Themes')
            if themeId:
                theme = self.session.get(themeId, self.session.getApplication().getSheetMetadata('Themes'))
                sObj[theme.getSheetId()] = theme.getPrivateData()

        else:
            sObj = StringIO()
            sObj.write('{\n')
            write_line(sObj, self.sheet.getSheetId(), self.sheet.getPrivateData())

            themeId = self.sheet.getValue('Themes')
            if themeId:
                theme = self.session.get(themeId, self.session.getApplication().getSheetMetadata('Themes'))
                write_line(sObj, theme.getSheetId(), theme.getPrivateData())

        for referenceCell in self.sheet.getSheetMetadata().getOneToManyList():
            excludeList = self.excludeListDict.get(self.sheet.getSheetMetadata().getSheetId()) or []
            if referenceCell.isCascade() and not excludeList.__contains__(referenceCell.getSheetId()):
                for child in self.session.getList(self.sheet, referenceCell):
                    self.serialize_records(sObj, child)

        if self.dictionary:
            return sObj
        sObj.write('\n}')
        return sObj.getvalue()
