"""
This script rewrites the filelist.rst file autogenerated by breathe to organize
the files in the documentation's API into the same directory structure as their
counterparts in the ../Source directory.

Note that we are not going to include cpp files - doxygen assumes that functions
are documented in the header files, so that's what we'll assume here as well.
"""

import os
import re

# directory of the source files
rootdir = "../Source"

filelist_path = "source/filelist.rst"


def strip_directives(filename, filepath, outpath):
    """
    Read in file, remove all preprocessor directives and output
    """

    r = re.compile(r"^#.*$\n")

    with open(os.path.join(filepath, filename)) as infile:
        txt = infile.read()

        outtxt = re.sub(r, '', txt)

        with open(os.path.join(outpath, filename), 'w') as outfile:
            outfile.write(outtxt)


def fortran_apidoc(filename, filepath):
    """
    Generate the sphinx-fortran boilerplate for the Fortran file filename.
    """

    rst_name = "source/file/" + filename[:-4] + "_f.rst"

    output_data = ""

    r = re.compile(
        r"^[\t ]*(module|subroutine|program|function) ([\w_]+)", re.M)

    # find modules / subroutines / programs / functions
    with open(os.path.join(filepath, filename)) as fortran_file:

        txt = fortran_file.read()

        output_data = """{}
{}

""".format(filename, '=' * len(filename))

        # if there are no matches, do nothing
        if r.search(txt) is None:
            return

        last_pos = 0

        m = re.search(r, txt)

        while m is not None:
            # module, subroutine, program or function?
            element = m.group(1)

            # name of thing
            name = m.group(2).lower()

            title_name = name.replace('_', '\_')

            if element != "module":
                title_name += ' ' + element

            if element == "module":
                output_data += """{}
{}

.. f:automodule:: {}

""".format(title_name, '-' * len(title_name), name)

            elif element == "program":
                output_data += """{}
{}

.. f:automodule:: {}

""".format(title_name, '-' * len(title_name), name)

            elif element == "subroutine":

                output_data += """{}
{}

.. f:autosubroutine:: {}

""".format(title_name, '-' * len(title_name), name)

            elif element == "function":
                output_data += """{}
{}

.. f:autofunction:: {}

""".format(title_name, '-' * len(title_name), name)

            # now find the end of the module/subroutine/function/program
            r_end = re.compile(
                r"^[\t ]*end {} {}[\t ]*$".format(element, m.group(2)), re.M)

            end_match = re.search(r_end, txt)

            last_pos = end_match.end()

            m = re.search(r, txt[last_pos:])

    with open(rst_name, 'w') as rst_file:

        rst_file.write(output_data)


if __name__ == "__main__":

    with open(filelist_path, 'w') as outfile:

        output_data = """File list
=========

.. toctree::
   :maxdepth: 2

   """

        # loop over rootdir
        for f in sorted(os.listdir(rootdir)):
            if not os.path.isdir(os.path.join(rootdir, f)) and f[-2:] == ".H" and f[-4:] != "_F.H":
                output_data += r"""file/{}
   """.format(f[:-2] + '_8H.rst')

        # next iterate over subdirectories

        for subdir in sorted(os.listdir(rootdir)):
            if not os.path.isdir(os.path.join(rootdir, subdir)) or subdir == "param":
                continue

            output_data += r"""{}_files
   """.format(subdir)
            subdir_file_name = "source/{}_files.rst".format(subdir)

            with open(subdir_file_name, 'w') as subdir_file:

                subdir_output_data = "{}\n".format(subdir.capitalize())
                subdir_output_data += "=" * len(subdir)
                subdir_output_data += """

.. toctree::
   :maxdepth: 2

   """

                for f in sorted(os.listdir(os.path.join(rootdir, subdir))):
                    if f[-2:] == ".H" and f[-4:] != "_F.H":
                        rst_name = re.sub("_", "__", f)
                        rst_name = re.sub("\.", "_8", rst_name)

                        subdir_output_data += """file/{}
   """.format(rst_name)
                    elif f[-4:] == ".F90" or f[-4:] == ".f90":

                        fortran_apidoc(f, os.path.join(rootdir, subdir))

                        subdir_output_data += """file/{}
   """.format(f[:-4] + "_f")

                subdir_file.write(subdir_output_data)

        outfile.write(output_data)
