#!/usr/bin/python

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

# Django set up

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

g = globals()

def enum_classes():
	model_classes = []
	for c in g.values():
		if type(c)==type(PlCoreBase):
			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.title()
		
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():
			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)
			
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()
