#!/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 <classes.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.txt","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

	for n in range(0,columns):
		if (len(fit_columns[n])>row_max):
			row_max=len(fit_columns[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.lower()+"|"+classname+"]]|"

		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="[["+tag_text.lower()+"|"+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.lower()+"#"+method_param+"|"+class_param+'.'+method_param+"]]"
    else:
     tag_text="[[#"+param+"|"+param+"]]"
   elif (cmd.find("image=")==0):
    tag_text="{{"+cmd[6:]+"}}"
   elif (cmd.find("url=")==0):
    tag_text="[["+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.lower()+"|"+t+"]]"
	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"]+"**"
	else:
		s+="[[#"+m.attrib["name"]+"|"+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(name.lower()+".txt","wb")

	f.write("======  "+name+"  ======\n")

	if ("inherits" in node.attrib):
		inh=node.attrib["inherits"].strip()
		f.write("**Inherits:** [["+inh.lower()+"|"+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("=====  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("=====  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("=====  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("=====  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("=====  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("=====  Description  ======\n")
		f.write(dokuize_text(descr.text.strip())+"\n")

	methods = node.find("methods")

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

			d=m.find("description")
			if (d==None or d.text.strip()==""):
				continue
			f.write("==  "+m.attrib["name"]+"  ==\n")
			make_method(f,node.attrib["name"],m,False)
			f.write("\\\\\n")
			f.write(dokuize_text(d.text.strip()))
			f.write("\n")





	"""
  div=ET.Element("div")
  div.attrib["class"]="class";

  a=ET.SubElement(div,"a")
  a.attrib["name"]=node.attrib["name"]

  h3=ET.SubElement(a,"h3")
  h3.attrib["class"]="title class_title"
  h3.text=node.attrib["name"]

  briefd = node.find("brief_description")
  if (briefd!=None):
   div2=ET.SubElement(div,"div")
   div2.attrib["class"]="description class_description"
   div2.text=briefd.text

  if ("inherits" in node.attrib):
   ET.SubElement(div,"br")

   div2=ET.SubElement(div,"div")
   div2.attrib["class"]="inheritance";

   span=ET.SubElement(div2,"span")
   span.text="Inherits: "

   make_type(node.attrib["inherits"],div2)

  if ("category" in node.attrib):
   ET.SubElement(div,"br")

   div3=ET.SubElement(div,"div")
   div3.attrib["class"]="category";

   span=ET.SubElement(div3,"span")
   span.attrib["class"]="category"
   span.text="Category: "

   a = ET.SubElement(div3,"a")
   a.attrib["class"]="category_ref"
   a.text=node.attrib["category"]
   catname=a.text
   if (catname.rfind("/")!=-1):
    catname=catname[catname.rfind("/"):]
   catname="CATEGORY_"+catname

   if (single_page):
    a.attrib["href"]="#"+catname
   else:
    a.attrib["href"]="category.html#"+catname


  methods = node.find("methods")

  if(methods!=None and len(list(methods))>0):

   h4=ET.SubElement(div,"h4")
   h4.text="Public Methods:"

   method_table=ET.SubElement(div,"table")
   method_table.attrib["class"]="method_list";

   for m in list(methods):
#    li = ET.SubElement(div2, "li")
    method_table.append( make_method_def(node.attrib["name"],m,False) )

  events = node.find("signals")

  if(events!=None and len(list(events))>0):
   h4=ET.SubElement(div,"h4")
   h4.text="Events:"

   event_table=ET.SubElement(div,"table")
   event_table.attrib["class"]="method_list";

   for m in list(events):
#    li = ET.SubElement(div2, "li")
    event_table.append( make_method_def(node.attrib["name"],m,False,True) )


  members = node.find("members")
  if(members!=None and len(list(members))>0):

   h4=ET.SubElement(div,"h4")
   h4.text="Public Variables:"
   div2=ET.SubElement(div,"div")
   div2.attrib["class"]="member_list";

   for c in list(members):

    li = ET.SubElement(div2, "li")
    div3=ET.SubElement(li,"div")
    div3.attrib["class"]="member";
    make_type(c.attrib["type"],div3)
    span=ET.SubElement(div3,"span")
    span.attrib["class"]="identifier member_name"
    span.text=" "+c.attrib["name"]+" "
    span=ET.SubElement(div3,"span")
    span.attrib["class"]="member_description"
    span.text=c.text


  constants = node.find("constants")
  if(constants!=None and len(list(constants))>0):

   h4=ET.SubElement(div,"h4")
   h4.text="Constants:"
   div2=ET.SubElement(div,"div")
   div2.attrib["class"]="constant_list";

   for c in list(constants):
    li = ET.SubElement(div2, "li")
    div3=ET.SubElement(li,"div")
    div3.attrib["class"]="constant";

    span=ET.SubElement(div3,"span")
    span.attrib["class"]="identifier constant_name"
    span.text=c.attrib["name"]+" "
    if ("value" in c.attrib):
     span=ET.SubElement(div3,"span")
     span.attrib["class"]="symbol"
     span.text="= "
     span=ET.SubElement(div3,"span")
     span.attrib["class"]="constant_value"
     span.text=c.attrib["value"]+" "
    span=ET.SubElement(div3,"span")
    span.attrib["class"]="constant_description"
    span.text=c.text

#  ET.SubElement(div,"br")


  descr=node.find("description")
  if (descr!=None and descr.text.strip()!=""):

   h4=ET.SubElement(div,"h4")
   h4.text="Description:"

   make_text_def(node.attrib["name"],div,descr.text)
#   div2=ET.SubElement(div,"div")
#   div2.attrib["class"]="description";
#   div2.text=descr.text



  if(methods!=None or events!=None):

   h4=ET.SubElement(div,"h4")
   h4.text="Method Documentation:"
   iter_list = []
   if (methods!=None):
    iter_list+=list(methods)
   if (events!=None):
    iter_list+=list(events)

   for m in iter_list:

    descr=m.find("description")

    if (descr==None or descr.text.strip()==""):
     continue;

    div2=ET.SubElement(div,"div")
    div2.attrib["class"]="method_doc";


    div2.append( make_method_def(node.attrib["name"],m,True) )
	#anchor = ET.SubElement(div2, "a")
	#anchor.attrib["name"] =
    make_text_def(node.attrib["name"],div2,descr.text)
    #div3=ET.SubElement(div2,"div")
    #div3.attrib["class"]="description";
    #div3.text=descr.text


  return div
"""
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,4)

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