<reponame>Grepstar/GSParseSchema
__author__ = 'dhallman'

import os

class LanguageSource(object):

    def __init__(self, languageName, prefix, dateString):
        self.languageName = languageName
        self.prefix = prefix
        self.dateString = dateString
        self.subclasses = []
        self.parseFieldsToSkip = ['objectId', 'ACL', 'createdAt', 'updatedAt']
        self.userFieldsToSkip = ['authData', 'email', 'emailVerified', 'username', 'password', 'role']
        self.fieldsToSkip = {
            'PFObject' : ['objectId', 'ACL', 'createdAt', 'updatedAt'],
            '_User' : ['authData', 'email', 'emailVerified', 'username', 'password', 'role'],
            '_Installation' : ['GCMSenderId', 'appIdentifier', 'appName', 'appVersion', 'badge', 'channels', 'deviceToken', 'deviceType', 'installationId', 'localeIdentifier', 'parseVersion', 'pushType', 'timeZone', 'user'],
            '_Role' : ['name', 'roles', 'users'],
            '_Product' : ['download', 'downloadName', 'icon', 'order', 'productIdentifier', 'subtitle', 'title']
        }

#############################################
# Methods to override in language subclasses
#############################################

    # Subclasses will likely call this super method first, then execute another method after completion
    def createImplementation(self, schemas=[]):
        # Create directory
        dir = os.getcwd() + '/' + self.languageName
        if not os.path.exists(dir):
            os.makedirs(dir)

        # Build list of subclasses
        subclassImportsByClass = {}

        # First iteration builds a list of all the subclasses and their cross-references to each other
        for schema in schemas:
            className = schema['className']
            isPrivateClass = className.startswith('_')

            # Create empty array of imports
            subclassImportsByClass[className] = []

            if isPrivateClass:
                # Internal Parse classes
                if className == '_User' or className == '_Installation':
                    baseName = className[1:]
                    subclassName = self.prefix + baseName
                else:
                    # Skip classes _Session and _Role
                    continue
            else:
                # Custom Parse classes
                subclassName = self.prefix + className

            # Build subclass list
            self.subclasses.append(subclassName)

            # Iterate to find subclasses which need to reference/import another subclass
            for field, fieldDict in schema['fields'].iteritems():
                type = fieldDict['type']

                if type == 'Pointer':
                    typeClass = self.determineSubclassName(fieldDict['targetClass'])
                    if typeClass == None:
                        # No subclass
                        continue

                    # If not in the list, then add it
                    imports = subclassImportsByClass[className]
                    if typeClass not in imports:
                        imports.append(typeClass)

        # Second iteration creates the source code
        for schema in schemas:
            className = schema['className']
            isPrivateClass = className.startswith('_')
            subclassImports = subclassImportsByClass[className]

            if isPrivateClass:
                # Internal Parse classes
                if className == '_User' or className == '_Installation':
                    baseName = className[1:]
                    subclassName = self.prefix + baseName
                else:
                    # Skip classes _Session and _Role
                    continue
            else:
                # Custom Parse classes
                subclassName = self.prefix + className

            # Create the source
            print 'Generate {} subclass {} for Parse class {}'.format(self.languageName, subclassName, className)
            self.generateSubclass(schema, parseClassName=className, subclassName=subclassName, isPrivateClass=isPrivateClass, subclassImports=subclassImports)

    # Override this method to create the source code
    def generateSubclass(self, schema, parseClassName='', subclassName='', isPrivateClass=False, subclassImports=[]):

        # Filename
        fileName = subclassName + '.txt'

        # Header
        source = self.generateComments(fileName)

        # Body
        source = 'Source goes here\n\n'

        # Save
        self.saveFile(fileName, source)

    # Override this method change the commented header
    def generateComments(self, fileName):
        source = '//\n'
        source += '// {}\n'.format(fileName)
        source += '//\n'
        source += '// Auto-generated by GSParseSchema on {}.\n'.format(self.dateString)
        source += '// https://github.com/Grepstar/GSParseSchema\n'
        source += '//\n\n'
        return source

##########
# Helpers
##########

    # Helper method to determine subclass name from the Parse model
    def determineSubclassName(self, className=''):
        if className == '_User' or className == '_Installation':
            return self.prefix + className[1:]
        elif className.startswith('_'):
            return None
        else:
            return self.prefix + className

    def saveFile(self, fileName, source):
        # Remove old file if it exists
        filePath = self.languageName + '/' + fileName
        if os.path.exists(filePath):
            os.remove(filePath)

        # Save file
        file = open(filePath, 'w')
        file.write(source)
        file.close()

        print '\tCreated {}'.format(filePath)
