#!/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)

from core.models import ModelLink

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

# syntax: mldeps [-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 = {}
    tl = {}
    for c in model_classes:
        fields = c._meta.fields
        try:
            exp_links = c.xos_links
        except AttributeError:
            exp_links = []
        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__]

        for l in exp_links:
            linked_class = l.dest
            if (type(linked_class)==str):
                linked_class = lower_class_names[linked_class.lower()]
            via = l.via
            if ('backref' in via):
                a = linked_class.__name__
                b = c.__name__
            else:
                b = linked_class.__name__
                a = c.__name__

            try:
                if (b not in tl[a]):
                    tl[a].append(b)
            except KeyError:
                tl[c.__name__]=[linked_class.__name__]


    #d['ControllerNetwork'].append('SliceDeployments')
    print json.dumps(tl,indent=4)
