#!/usr/bin/env python3

import os.path
import re
import sys

def process_comment(fd, comment, first_param, last_param):
    if first_param < 0:
        # Nothing to do: just copy the comment
        fd.write("".join(comment))
    else:
        params = list()

        # Copy the non param lines unmodified:
        fd.write("".join(comment[:first_param]))

        # Measure the indentation of the first param and use that to create an empty comment line string:
        m = re.match(r" *\*", comment[first_param])

        if not m:
            raise Exception("Not a comment ? '{}'".format(comment[first_param]))

        empty_line = "{}\n".format(m.group(0))

        # For each param split the line into 3 columns: param, param_name, description
        for param in range(first_param, last_param):
            m = re.match(r"([^@]+@param\[[^\]]+\]) +(\S+) +(.+)", comment[param])

            if m:
                params.append( (m.group(1), m.group(2), m.group(3)) )
            else:
                # If it's not a match then it must be a multi-line param description:

                m = re.match("( *\*) +(.*)", comment[param])

                if not m:
                    raise Exception("Not a comment line ? ({})".format(n_line - len(comment) + param))

                params.append( (m.group(1), "", m.group(2)) )

        # Now that we've got a list of params, find what is the longest string for each column:
        max_len = [0, 0]

        for p in params:
            for l in range(len(max_len)):
                max_len[l] = max(max_len[l], len(p[l]))

        # Insert an empty line if needed before the first param to make it easier to read:
        m = re.match(r" *\* *$", comment[first_param - 1])

        if not m:
            # insert empty line
            fd.write(empty_line)

        # Write out the formatted list of params:
        for p in params:
            fd.write("{}{} {}{} {}\n".format(
                    p[0], " " * (max_len[0] - len(p[0])),
                    p[1], " " * (max_len[1] - len(p[1])),
                    p[2]))

        # If the next line after the list of params is a command (@return, @note, @warning, etc), insert an empty line to separate it from the list of params
        if last_param < len(comment) - 1:
            if re.match(r" *\* *@\w+", comment[last_param]):
                # insert empty line
                fd.write(empty_line)

        # Copy the remaining of the comment unmodified:
        fd.write("".join(comment[last_param:]))

if __name__ == "__main__":
    n_file=0

    if len(sys.argv) == 1:
        paths = []

        for top_level in ["./arm_compute", "./src", "./examples", "./tests", "./utils", "./framework", "./support"]:
            for root, _, files in os.walk(top_level):
                paths.extend([os.path.join(root, f) for f in files])
    else:
        paths = sys.argv[1:]

    for path in paths:
        if (path[-3:] not in ("cpp", "inl") and
            path[-2:] not in ("cl") and
            path[-1] not in ("h")):
            continue

        print("[{}] {}".format(n_file, path))

        n_file += 1

        with open(path,'r+', encoding="utf-8") as fd:
            comment = list()
            first_param = -1
            last_param = -1
            n_line = 0

            lines = fd.readlines()
            fd.seek(0)
            fd.truncate()

            for line in lines:
                n_line += 1

                # Start comment
                # Match C-style comment /* anywhere in the line
                if re.search(r"/\*", line):
                    #print("Start comment {}".format(n_line))

                    if len(comment) > 0:
                        raise Exception("Already in a comment! ({})".format(n_line))

                    comment.append(line)

                # Comment already started
                elif len(comment) > 0:
                    #print("Add line to comment {}".format(n_line))

                    comment.append(line)

                # Non-comment line
                else:
                    #print("Normal line {}".format(n_line))

                    fd.write(line)

                # Match param declaration in Doxygen comment
                # @param[in] name description
                if re.search(r"@param\[[^\]]+\] +\S+ +\S", line):
                    #print("Param {}".format(n_line))

                    if first_param < 0:
                        first_param = len(comment) - 1

                    last_param = len(comment)

                # Match end of C-style comment */
                if re.search(r"\*/", line):
                    if re.search('"[^"]*\*/[^"]*"', line):
                        #print("End of comment inside a string: ignoring")
                        pass
                    else:
                        #print("End comment {}".format(n_line))

                        if len(comment) < 1:
                            raise Exception("Was not in a comment! ({})".format(n_line))

                        #print("Process comment {} {}".format(first_param, last_param))

                        process_comment(fd, comment, first_param, last_param)

                        comment = list()
                        first_param = -1
                        last_param = -1
