import sys
import re
#First argument is the filename
fileName = sys.argv[1]


def stopLoopLinesClass(line):
    if ("public" in line):  return True
    if ("private" in line): return True
    if ("(" in line):       return True
    if (")" in line):       return True
    if ("}" in line):       return True
    return False

def FormatClasses(class_full):        
    class_full = re.split("\n",class_full)

    name = class_full[0].replace("class ","")[0:-1]
    public_vars = []
    private_vars = []
    functions = []

    for idx,line in enumerate(class_full[1:]):
        line = line[4:] #Remove the indent
        if (line.startswith("    ")): continue     
        if (line.startswith("public:") or line.startswith("ic:")):
            idx = idx+1 
            while (not stopLoopLinesClass(class_full[idx+1])):                                
                public_vars.append(class_full[idx+1].lstrip())
                idx = idx+1        
        if (line.startswith("private:") or line.startswith("te:")):
            idx = idx+1 
            while (not stopLoopLinesClass(class_full[idx+1])):
                private_vars.append(class_full[idx].lstrip())
                idx = idx+1       
        if ("(" in line): 
            tmp = line
            if (")" not in line):       
                while (")" not in class_full[idx]):
                    tmp = tmp + class_full[idx].strip()
                    idx = idx+1
                tmp = tmp + class_full[idx].strip()
            functions.append(tmp)         

    return name, public_vars, private_vars, functions


def isPythonFile(fileName):
    if (fileName.endswith(".py")): 
        return True
    else: 
        return False

def ReadFile(fileName): #Returns the read lines and an integer, that is true when the file if a python file
    with open(fileName) as f:
        lines = f.readlines()
    return lines

def AddCommentWithLink(functionName, isPython):
    #Strip the data type from the title and add ()
    functionTitle = functionName
    if (not isPython): functionTitle = functionTitle[functionTitle.rfind(' '):]
    # Now parse the name to create the link
    functionLink = functionName
    for symbol in [" ","::"]:
        functionLink = functionLink.replace(symbol,"-")
    for symbol in ["(",")","\*","*"]:        
        functionLink = functionLink.replace(symbol,"-")
    #Print the reference as it would be used in text
    return ("[comment]: # (["+functionTitle.strip()+"()](#" + functionLink.lower()+ "))")

def ReadCpp(lines):
    globals_list = []
    function_list = []
    classes_list = []


    for idx,line in enumerate(lines):
        if (line.startswith("    ")): continue
        if (line.startswith("}")): continue
        if (line.startswith("//")): continue
        if (line.startswith("#")): continue
        if (line.startswith("using")): continue
        if (line.startswith("class")):         
            tmp = ""
            while ("};" not in lines[idx]):
                tmp = tmp + lines[idx]
                idx = idx+1
            tmp = tmp + lines[idx].strip()
            classes_list.append(tmp)
        if (line.startswith("struct")):         
            tmp = ""
            while ("}" not in lines[idx]):
                tmp = tmp + lines[idx]
                idx = idx+1
            tmp = tmp + lines[idx].strip()
            classes_list.append(tmp)
                    
        if (line.isspace()): continue
        if ("(" not in line): globals_list.append(line.strip())
        elif (")" not in line):        
            tmp = ""
            while (")" not in lines[idx]):
                tmp = tmp + lines[idx].strip()
                idx = idx+1
            tmp = tmp + lines[idx].strip()
            function_list.append(tmp)
        else: function_list.append(line.strip())    

    for cl in classes_list: FormatClasses(cl)

    globals = []
    for glob in globals_list:
        glob = glob.replace(";","")
        for tmp in glob.split(','): globals.append(tmp.lstrip())

    print("\n\n## Global variables:\n")
    for tmp in globals: print("* "+tmp)

    print("\n\n# Classes")

    for cl in classes_list: 
        name, pub, priv, funcs = FormatClasses(cl)
        print ("### "+name)
        print ("* **Private members:**")
        for p in priv:
            print("    * "+ p.replace(";",""))
        print ("* **Public  members:**")
        for p in pub:
            print("    * "+ p.replace(";",""))
        print ("* **Functions:**")
        for f in funcs:
            f = f.replace("){","")
            f = f.replace(") {","")
            f = f.replace("*","\*")
            funcs = f.split("(")
            funcs[1] = funcs[1].split(',')
            if (len(funcs[1])>0) and (funcs[1][0].strip()!=""): 
                print("    * **"+funcs[0]+"()**\n")
                print (AddCommentWithLink(funcs[0],False))
                print("        * **Parameters**")
                for params in funcs[1]:
                    print("            * "+params.lstrip())                        
                print("        * **Return**")
            elif ("~" in funcs[0]): print("    * **"+funcs[0]+"()** // destructor")
            else: print("    * **"+funcs[0]+"()** // constructor")

    print("\n\n\n# Functions")
    functions = []
    for funcs in function_list:
        funcs = funcs.replace("){","")
        funcs = funcs.replace(") {","")
        funcs = funcs.replace("*","\*")
        functions = funcs.split("(")
        functions[1] = functions[1].split(',')
        print("### "+functions[0]+"()")
        print(AddCommentWithLink(functions[0],False)+"\n")
        print("* **Parameters**")
        for params in functions[1]:
            print("    * "+params.lstrip())
        if ("void " not in functions[0]): print("* **Return**\n")
        else: print("\n")
    return


def ReadPython(lines):
    globals_list = []
    function_list = []
    classes_list = []

    for idx,line in enumerate(lines):
        if (line.startswith("  ")): continue
        if (line.startswith("#")): continue #Remove comments
        if (line.startswith("import")): continue
        if (line == "\n"): continue #Remove empty lines
        if (line.startswith("def")):      
            line = line.replace(":","")   
            if (")" not in line):     
                tmp = ""
                while (")" not in lines[idx]):
                    tmp = tmp + lines[idx].strip()
                    idx = idx+1
                tmp = tmp + lines[idx].strip()
                function_list.append(tmp)
            else: function_list.append(line.strip())                              
        else:                 
            globals_list.append(line.strip())



    print("\n\n## Global variables:\n")
    for tmp in globals_list: print("* "+tmp)

    
    print("\n\n\n# Functions")
    functions = []
    for funcs in function_list:
        funcs = funcs.replace(")","")        
        funcs = funcs.replace("def ","")        
        funcs = funcs.replace("*","\*")
        functions = funcs.split("(")
        functions[1] = functions[1].split(',')
        print("### "+functions[0]+"()\n")
        print(AddCommentWithLink(functions[0],True)+"\n")
        print("* **Parameters**")
        for params in functions[1]:
            print("    * "+params.lstrip())
        print("* **Return**\n")
    return


##### The main run

if (isPythonFile(fileName)): 
    ReadPython(ReadFile(fileName))
else : 
    ReadCpp(ReadFile(fileName))
