#!/usr/bin/python

import os
import pdb
import sys
import json

sys.path.append('.')

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")

from django.db.models.fields.related import ForeignKey

# try to make sure we're running from the right place
if (not os.path.exists("core")):
   if (os.path.exists("../core")):
      os.chdir("..")
   else:
      print >> sys.stderr, "Are you sure you're running dmdot from the root of an XOS installation"
      sys.exit(-1)

# defaults
apps = ["core", "services.hpc", "services.cord", "services.requestrouter", "services.onos"]
output = "-json"

# syntax: dmdot [-json | -dot] [app_name]

# poor man's argument parser
for arg in sys.argv[1:]:
    if arg.startswith("-"):
        output = arg
    else:
        apps+= [arg]

model_classes = []
class_names = []
lower_class_names = {}
synonyms = {
	'user':'creator'
}

for app in apps:
	app = app + ".models"
	#models_module = imp.load_source(app, ".")
	models_module = __import__(app)
	for part in app.split(".")[1:]:
	    if hasattr(models_module, "PlCoreBase"):
		break
	    models_module = getattr(models_module,part)

	PlCoreBase = getattr(models_module,"PlCoreBase")

	for classname in dir(models_module):
		c = getattr(models_module, classname, None)
		if type(c)==type(PlCoreBase):
			model_classes.append(c)
			class_names.append(c.__name__)
			lower_class_names[c.__name__.lower()] = c
			try:
				synonym = synonyms[c.__name__.lower()]
				lower_class_names[synonym] = c
			except: 
				pass    
				

# django doesn't use the correct case in field.name.title() for objects that
# have CamelCased class names. So, compare everything in lower case.

if (output=='-dot'):
        print "digraph plstack {";
        for c in model_classes:
                fields = c._meta.fields

                for f in fields:
                        if type(f)==ForeignKey and f.name.lower().split('_') in lower_class_names:
                                linked_class = lower_class_names[f.name.lower()]
				if ('backref' in f.name):
                                	print '\t"%s"->"%s";'%(linked_class.__name__,c.__name__)
				else:
                                	print '\t"%s"->"%s";'%(c.__name__,linked_class.__name__)
        print "}\n";
elif (output=='-json'):
        d = {}
        for c in model_classes:
                fields = c._meta.fields
		
                for f in fields:
			field_type = f.name.lower().split('_')[0]
                        if type(f)==ForeignKey and field_type in lower_class_names:
                                linked_class = lower_class_names[field_type]
				if ('backref' in f.name.lower()):
					a = linked_class.__name__
					b = c.__name__
				else:
					b = linked_class.__name__
					a = c.__name__

                                try:
					if (b not in d[a]):
                                        	d[a].append(b)
                                except KeyError:
                                        d[c.__name__]=[linked_class.__name__]
        #d['ControllerNetwork'].append('SliceDeployments')
        print json.dumps(d,indent=4)
        
        
