#!/usr/bin/python

import os
import pdb
import copy
import sys
import json
import re
from django.template import Context, Template
from optparse import OptionParser

# Django set up

sys.path.append('.')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
from django.db.models.fields.related import ForeignKey, ManyToManyField

options = None


def singular(foo, keys):
	for k in keys:
		if (foo==k+'es'):
			return k
		elif (foo==k+'s'):
			return k
	raise Exception('Plural to singular error for %s'%foo)

g = globals()

def enum_classes(apps):
    global app_map
    app_map = {}
    model_classes = []
    for app in apps:
            orig_app=app
            app = app + ".models"
            models_module = __import__(app)
            for part in app.split(".")[1:]:
                if hasattr(models_module, "PlCoreBase"):
                    break
                models_module = getattr(models_module,part)

            global PlCoreBase
            PlCoreBase = getattr(models_module,"PlCoreBase")

            for classname in dir(models_module):
                    c = getattr(models_module, classname, None)
                    if type(c)==type(PlCoreBase) and c.__name__ not in options.blacklist:
                            model_classes.append(c)
                            app_map[c.__name__]=orig_app


    return model_classes

class GenObj(object):
	def __str__(self):
		return str(self.model.__name__.lower())

	def __init__(self, m):
		self.model = m
		self.props = []
		self.fields = []
		self.field_dict = []
		self.refs = []
		self.plural_name = None

	def plural(self):
		if (self.plural_name):
			return self.plural_name
		else:
			name = str(self)
			if (name.endswith('s')):
				return name+'es'
			else:
				return name+'s'

        def singular(self):
            return str(self)

        def rest_name(self):
            # These are things that either for historic reasons or due to incorrect naming,
            # got called something different than the autogen thinks they should be
            # called.
            REST_FIXUP = {'controllernetworkses': 'controllernetworks',
                            'controllerimageses': 'controllerimages',
                            'controllersliceses': 'controllerslices',
                            'controlleruserses': 'controllerusers',
                            'sitedeploymentses': 'sitedeployments',
                            'siteroles': 'site_roles',
                            'sliceprivileges': 'slice_privileges',
                            'sliceroles': 'slice_roles',
                            }
            return REST_FIXUP.get(self.plural(), self.plural())

	def camel(self):
		name = str(self.model.__name__)
		return name
		
class Generator(dict):
	def all(self):
		return self.values()

        def rest_models(self):
                norest = [x.lower() for x in options.norest]
                return [v for v in self.values() if not (str(v) in norest)]
	
	def regex(self, r):
		filtered = filter(lambda o:re.match(r,str(o)), self.values())
		return filtered

	def add_object(self, o):
                global app_map
		obj = GenObj(o)
		fields = o._meta.fields
                try:
                    obj.app = app_map[o.__name__]
                except KeyError:
                    print "KeyError: %r"%o.__name__
                    pdb.set_trace()
		self[str(obj).lower()]=obj

	def compute_links(self):
                base_props = [f.name for f in PlCoreBase._meta.fields]

		for obj in self.values():
			#if (str(obj)=='network'):
			#	pdb.set_trace()
			fields = obj.model._meta.fields
			for f in fields:
				if (f and f.rel):
					to_name = str(f.rel.to)
				else:
					to_name = None

				if type(f)==ForeignKey and to_name and to_name in self.keys():
					refobj = self[f.to_name]

					if (str(obj)=='slice' and f.to_name=='networks'):
						obj.refs.append(refobj)
					related_name = f.related_query_name()
					if (related_name!='+' and related_name.lower()!=str(obj).lower()):
						cobj = copy.deepcopy(obj)
						cobj.multi = True
						cobj.plural_name = related_name
						refobj.refs.append(cobj)
                                elif f.name.endswith("_ptr"):
                                        # django inherited model, for example HPCService
                                        # cause swagger and REST to break
                                        pass
				else:
                                        f.type = f.__class__.__name__

                                        if (f.name not in base_props):
                                            obj.fields.append(f) 
                                        obj.props.append(f.name)

			m2m = obj.model._meta.many_to_many
			for f in m2m:
				try:
					related_model_name = f.m2m_reverse_field_name()
				except:
					related_model_name = f.m2m_db_table().rsplit('_',1)[-1]

				related_name = f.related_query_name()
				if related_model_name in self.keys():
                                        #print "XXX1", obj, f, related_name, related_model_name
					refobj = self[related_model_name]
					cobj = copy.deepcopy(obj)
					cobj.multi=True
					refobj.refs.append(cobj)

                                # deal with upgradeFrom_rel_+
                                if (related_name.endswith("+")):
                                    continue

				if (related_name!='+') and related_model_name in self: # and related_name.lower()!=str(obj).lower()):
                                        refobj = self[related_model_name]
                                        #print "XXX2", obj, f, related_name, related_model_name, refobj.plural_name
					cobj = copy.deepcopy(refobj)
					cobj.multi = True

					obj.refs.append(cobj)




def main():
        global options
        parser = OptionParser(usage="modelgen [options] <template_fn>", )

        parser.add_option("-a", "--app", dest="apps",
             help="list of applications to parse", metavar="APP", default=[], action="append")
        parser.add_option("-b", "--blacklist", dest="blacklist",
             help="add model name to blacklist", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")
        parser.add_option("-n", "--no-rest", dest="norest",
             help="do not generate rest api for model", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")

        (options, args) = parser.parse_args(sys.argv[1:])

        if not options.apps:
            options.apps = ["core"]

        if len(args)!=1:
            print 'Usage: modelgen [options] <template_fn>'
            exit(1)

        template_name = os.path.abspath(args[0])

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

	generator = Generator()

	models = enum_classes(options.apps)

	for m in models:
		generator.add_object(m)

	generator.compute_links()
	template_contents = open(template_name).read()
	template = Template(template_contents)
	context = Context({'generator':generator})
	print template.render(context)


if (__name__=='__main__'):
	main()
