#!/usr/bin/python

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

blacklist = ['SingletonModel','PlCoreBase']

# Django set up

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

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():
	model_classes = []
	for c in g.values():
		if type(c)==type(PlCoreBase) and c.__name__ not in blacklist:
			model_classes.append(c)
	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.refs = []

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

	def camel(self):
		name = str(self.model.__name__)
		return name
		
class Generator(dict):
	def all(self):
		return self.values()
	
	def regex(self, r):
		filtered = filter(lambda o:re.match(r,str(o)), self.values())
		return filtered

	def add_object(self, o):
		obj = GenObj(o)
		fields = o._meta.fields
		self[str(obj).lower()]=obj

	def compute_links(self):
		for obj in self.values():
			if (str(obj).lower()=='user'):
				pdb.set_trace()
			fields = obj.model._meta.fields
			for f in fields:
				if type(f)==ForeignKey and f.name in self.keys():
					refobj = self[f.name]
					obj.refs.append(refobj)
				else:
					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]

				if related_model_name in self.keys():
					refobj = self[related_model_name]
					obj.multi=True
					refobj.refs.append(obj)

			
def main():
	try:
		output = sys.argv[1]
	except:
		print 'Usage: modelgen <output template>'
		exit(1)

	generator = Generator()

	models = enum_classes()

	for m in models:
		generator.add_object(m)

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


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