#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
import xml.etree.ElementTree as ET

input_list = []

for arg in sys.argv[1:]:
	input_list.append(arg)

if len(input_list) < 1:
	print 'usage: makedoku.py <class_list.xml>'
	sys.exit(0)


def validate_tag(elem, tag):
	if elem.tag != tag:
		print "Tag mismatch, expected '" + tag + "', got " + elem.tag
		sys.exit(255)


class_names = []
classes = {}


def make_class_list(class_list, columns):

	f = open('class_list.md', 'wb')
	prev = 0
	col_max = len(class_list) / columns + 1
	print ('col max is ', col_max)
	col_count = 0
	row_count = 0
	last_initial = ''
	fit_columns = []

	for n in range(0, columns):
		fit_columns += [[]]

	indexers = []
	last_initial = ''

	idx = 0
	for n in class_list:
		col = idx / col_max
		if col >= columns:
			col = columns - 1
		fit_columns[col] += [n]
		idx += 1
		if n[:1] != last_initial:
			indexers += [n]
		last_initial = n[:1]

	row_max = 0
	f.write("\n")
	
	for n in range(0, columns):
		if len(fit_columns[n]) > row_max:
			row_max = len(fit_columns[n])

	f.write("| ")
	for n in range(0, columns):
		f.write(" | |")

	f.write("\n")		
	f.write("| ")
	for n in range(0, columns):
		f.write(" --- | ------- |")
	f.write("\n")

	for r in range(0, row_max):
		s = '| '
		for c in range(0, columns):
			if r >= len(fit_columns[c]):
				continue

			classname = fit_columns[c][r]
			initial = classname[0]
			if classname in indexers:
				s += '**' + initial + '** | '
			else:
				s += ' | '

			s += '[' + classname + '](class_'+ classname.lower()+') | '

		s += '\n'
		f.write(s)


def dokuize_text(txt):

	return txt


def dokuize_text(text):
	pos = 0
	while True:
		pos = text.find('[', pos)
		if pos == -1:
			break

		endq_pos = text.find(']', pos + 1)
		if endq_pos == -1:
			break

		pre_text = text[:pos]
		post_text = text[endq_pos + 1:]
		tag_text = text[pos + 1:endq_pos]

		if tag_text in class_names:
			tag_text = make_type(tag_text)
		else:

		# command

			cmd = tag_text
			space_pos = tag_text.find(' ')
			if cmd.find('html') == 0:
				cmd = tag_text[:space_pos]
				param = tag_text[space_pos + 1:]
				tag_text = '<' + param + '>'
			elif cmd.find('method') == 0:
				cmd = tag_text[:space_pos]
				param = tag_text[space_pos + 1:]

				if param.find('.') != -1:
					(class_param, method_param) = param.split('.')
					tag_text = '['+class_param+'.'+method_param.replace("_","&#95;")+'](' + class_param.lower() + '#' \
						+ method_param + ')'
				else:
					tag_text = '[' + param.replace("_","&#95;") + '](#' + param + ')'
			elif cmd.find('image=') == 0:
				tag_text = '![](' + cmd[6:] + ')'
			elif cmd.find('url=') == 0:
				tag_text = '[' + cmd[4:] + ']('+cmd[4:]
			elif cmd == '/url':
				tag_text = ')'
			elif cmd == 'center':
				tag_text = ''
			elif cmd == '/center':
				tag_text = ''
			elif cmd == 'br':
				tag_text = '\n'
			elif cmd == 'i' or cmd == '/i':
				tag_text = '_'
			elif cmd == 'b' or cmd == '/b':
				tag_text = '**'
			elif cmd == 'u' or cmd == '/u':
				tag_text = '__'
			else:
				tag_text = '[' + tag_text + ']'

		text = pre_text + tag_text + post_text
		pos = len(pre_text) + len(tag_text)

 # tnode = ET.SubElement(parent,"div")
 # tnode.text=text

	return text


def make_type(t):
	global class_names
	if t in class_names:
		return '[' + t + '](class_' + t.lower() + ')'
	return t


def make_method(
	f,
	name,
	m,
	declare,
	event=False,
	):

	s = '  * '
	ret_type = 'void'
	args = list(m)
	mdata = {}
	mdata['argidx'] = []
	for a in args:
		if a.tag == 'return':
			idx = -1
		elif a.tag == 'argument':
			idx = int(a.attrib['index'])
		else:
			continue

		mdata['argidx'].append(idx)
		mdata[idx] = a

	if not event:
		if -1 in mdata['argidx']:
			s += make_type(mdata[-1].attrib['type'])
		else:
			s += 'void'
		s += ' '

	if declare:

		# span.attrib["class"]="funcdecl"
		# a=ET.SubElement(span,"a")
		# a.attrib["name"]=name+"_"+m.attrib["name"]
		# a.text=name+"::"+m.attrib["name"]

		s += ' **'+m.attrib['name'].replace("_","&#95;")+'** '
	else:
		s += ' **['+ m.attrib['name'].replace("_","&#95;")+'](#' + m.attrib['name'] + ')** '

	s += ' **(**'
	argfound = False
	for a in mdata['argidx']:
		arg = mdata[a]
		if a < 0:
			continue
		if a > 0:
			s += ', '
		else:
			s += ' '

		s += make_type(arg.attrib['type'])
		if 'name' in arg.attrib:
			s += ' ' + arg.attrib['name']
		else:
			s += ' arg' + str(a)

		if 'default' in arg.attrib:
			s += '=' + arg.attrib['default']

		argfound = True

	if argfound:
		s += ' '
	s += ' **)**'

	if 'qualifiers' in m.attrib:
		s += ' ' + m.attrib['qualifiers']

	f.write(s + '\n')


def make_doku_class(node):

	name = node.attrib['name']

	f = open("class_"+name.lower() + '.md', 'wb')

	f.write('#  ' + name + '  \n')

	if 'inherits' in node.attrib:
		inh = node.attrib['inherits'].strip()
		f.write('####**Inherits:** '+make_type(inh)+'\n')
	if 'category' in node.attrib:
		f.write('####**Category:** ' + node.attrib['category'].strip()
				+ '\n')

	briefd = node.find('brief_description')
	if briefd != None:
		f.write('\n###  Brief Description  \n')
		f.write(dokuize_text(briefd.text.strip()) + '\n')

	methods = node.find('methods')

	if methods != None and len(list(methods)) > 0:
		f.write('\n###  Member Functions \n')
		for m in list(methods):
			make_method(f, node.attrib['name'], m, False)

	events = node.find('signals')
	if events != None and len(list(events)) > 0:
		f.write('\n###  Signals  \n')
		for m in list(events):
			make_method(f, node.attrib['name'], m, True, True)

	members = node.find('members')

	if members != None and len(list(members)) > 0:
		f.write('\n###  Member Variables  \n')

		for c in list(members):
			s = '  * '
			s += make_type(c.attrib['type']) + ' '
			s += '**' + c.attrib['name'] + '**'
			if c.text.strip() != '':
				s += ' - ' + c.text.strip()
			f.write(s + '\n')

	constants = node.find('constants')
	if constants != None and len(list(constants)) > 0:
		f.write('\n###  Numeric Constants  \n')
		for c in list(constants):
			s = '  * '
			s += '**' + c.attrib['name'] + '**'
			if 'value' in c.attrib:
				s += ' = **' + c.attrib['value'] + '**'
			if c.text.strip() != '':
				s += ' - ' + c.text.strip()
			f.write(s + '\n')

	descr = node.find('description')
	if descr != None and descr.text.strip() != '':
		f.write('\n###  Description  \n')
		f.write(dokuize_text(descr.text.strip()) + '\n')

	methods = node.find('methods')

	if methods != None and len(list(methods)) > 0:
		f.write('\n###  Member Function Description  \n')
		for m in list(methods):

			d = m.find('description')
			if d == None or d.text.strip() == '':
				continue
			f.write('\n#### <a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n')
			make_method(f, node.attrib['name'], m, True)
			f.write('\n')
			f.write(dokuize_text(d.text.strip()))
			f.write('\n')


for file in input_list:
	tree = ET.parse(file)
	doc = tree.getroot()

	if 'version' not in doc.attrib:
		print "Version missing from 'doc'"
		sys.exit(255)

	version = doc.attrib['version']

	for c in list(doc):
		if c.attrib['name'] in class_names:
			continue
		class_names.append(c.attrib['name'])
		classes[c.attrib['name']] = c

class_names.sort()

make_class_list(class_names, 2)

for cn in class_names:
	c = classes[cn]
	make_doku_class(c)

