# this file attempts to load a specified model.py file and extract the classes
# it then outputs xml to be used by SQLEditor

import os,sys,getopt
import imp
from django.core.management import setup_environ
import inspect

import emptysettings
setup_environ(emptysettings)

from django.db import models

import xml.etree.ElementTree as ET
from django.db.models.fields import NOT_PROVIDED


import uuid
import traceback

from pprint import pprint

# dynamically load a module file at the specified path
# including the  directory module
def loadModule(filepath):
    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    dirPath = os.path.split(filepath)

    fileName = dirPath[1];
    baseDir = dirPath[0];
    
    # first load the module containing the models.py file
    # then load the models.py file itself
    # otherwise we get a warning about the parent class

    baseModule = imp.load_source(baseDir,baseDir)
    mainModule = imp.load_source(baseDir+"."+mod_name,baseDir+"/"+fileName)
    
    return mainModule



def describe_class(obj):
   """ Describe the class object passed as argument,
   including its methods """

   tableNode = ET.Element("SQLTable")

   #print obj.__name__ + ' [model]'
   
   eName = ET.SubElement(tableNode,"name")
   eName.text = obj.__name__
   
   tableUid = ET.SubElement(tableNode,"uid")
   tableUid.text = str(uuid.uuid4())

   count = 0

   for aField in obj._meta.fields:
       #print aField.verbose_name + " "+aField.get_internal_type()
       fieldNode = ET.SubElement(tableNode,"SQLField")
       fieldName = ET.SubElement(fieldNode,"name")
       fieldName.text = aField.verbose_name
       
       fieldUid = ET.SubElement(fieldNode,"uid")
       fieldUid.text = str(uuid.uuid4())
       
       
       fieldType = ET.SubElement(fieldNode,"type")
       fieldType.text = aField.get_internal_type()
       
       if (aField.primary_key):
              fieldPK = ET.SubElement(fieldNode,"PrimaryKey")
              fieldPK.text = "1"
       if (aField.unique):
              fieldPK = ET.SubElement(fieldNode,"unique")
              fieldPK.text = "1"
       
       if ((aField.default) and (aField.default != NOT_PROVIDED)):
            fieldDefaultValue = ET.SubElement(fieldNode,"defaultValue")
            fieldDefaultValue.text = str(aField.default)
       
       if (aField.max_length):
            fieldTypeSize = ET.SubElement(fieldNode,"typeSize")
            fieldTypeSize.text = str(aField.max_length)
    
       
       
       if ("ForeignKey" == aField.get_internal_type()):
            fieldFkTable = ET.SubElement(fieldNode,"referencesTable")
            try:
                 fieldFkTable.text = aField.rel.to.__name__
            except AttributeError:
                fieldFkTable.text = aField.rel.to

            fieldFkTable = ET.SubElement(fieldNode,"referencesField")
            fieldFkTable.text = aField.rel.field_name
	   
   return tableNode




def xmlForModelClassesInModule(mainModule):
    
    document = ET.Element("SQLContainer")
    
    for name in dir(mainModule):
	
    
        obj = getattr(mainModule, name)
    
        # only interested in objects that are subclasses of the django model class
        
        if (inspect.isclass(obj)):
            if (issubclass(obj,models.base.Model)):
                table = describe_class(obj)
                document.append(table)
        #print "ok"
    #print ET.tostring(document)
    return document

def displayModelClassesInFilePath(filepath):

    docWrapper = ET.Element("SQLEditorDocument")
    

    
    try: 
        mainModule = loadModule(filepath)
        root = xmlForModelClassesInModule(mainModule)
        
        docWrapper.append(root)
    
	# There are lots of things that can go wrong.
    # Pass back errors in the XML document itself
    except AssertionError, e:
        sys.stderr.write('Error importing\n'+str(e)+'\n')
        
        error = ET.Element("SQLEditorError")
        
        errorReason = ET.Element("message")
        errorBacktrace = ET.Element("backtrace")
        
        errorReason.text = str(e)
        errorBacktrace.text = traceback.format_exc(1)

        error.append(errorReason)
        error.append(errorBacktrace)
        
        pluginResult = ET.Element("SQLEditorPluginResult")
        pluginResult.append(error)
        docWrapper.append(pluginResult)
	

    

    
    tree = ET.ElementTree(docWrapper)
    print '<?xml version="1.0" encoding="UTF-8"?>'
    tree.write(sys.stdout)
   
 
    
          

#filepath = "/Users/awh/Development/Experiments/djangotest/dbtest1/polls/models.py"
#filepath = "/Users/awh/temp/polls/models.py"


def main():
	filepath = sys.argv[2]
	#print "file path = "+filepath
	displayModelClassesInFilePath(filepath)



main()
