# -*- coding: utf-8 -*-
import os
import sys
import errno
import xml.etree.ElementTree


ALLOWED_TYPES = ['class', 'interface', 'struct', 'union']


def write_file(name, text, destdir):
    """Write the output file for module/package <name>."""
    fname = os.path.join(destdir, '%s.%s' % (name, 'rst'))

    if not os.path.exists(os.path.dirname(fname)):
        try:
            os.makedirs(os.path.dirname(fname))
        except OSError as exc:  # Guard against race condition
            if exc.errno != errno.EEXIST:
                raise
    try:
        with open(fname, 'r') as target:
            orig = target.read()
            if orig == text:
                return
    except FileNotFoundError:
        # Don't mind if it isn't there
        pass

    with open(fname, 'w') as target:
        target.write(text)


def format_heading(level, text):
    """Create a heading of <level> [1, 2 or 3 supported]."""
    underlining = ['=', '-', '~', ][level - 1] * len(text)
    return '%s\n%s\n\n' % (text, underlining)


def format_directive(package_type, package, project = None):
    """Create the breathe directive and add the options."""
    directive = '.. doxygen%s:: %s\n' % (package_type, package)
    if project:
        directive += '   :project: %s\n' % project
    return directive


def create_package_file(package, package_type, package_id, package_folder, rootpath, destdir):
    """Build the text of the file and write the file."""
    text = format_heading(1, '%s' % (package))
    text += format_directive(package_type, package)

    xmlfile = os.path.join(rootpath, package_id + '.xml')
    f = xml.etree.ElementTree.parse(os.path.join(xmlfile))

    write_file(os.path.join(package_folder, package_id), text, destdir)


def create_modules_toc_file(key, value, destdir):
    """Create the module's index."""
    text = format_heading(1, '%s' % value)
    text += '.. toctree::\n'
    text += '   :glob:\n\n'
    text += '   %s/*\n' % key

    write_file('%slist' % key, text, destdir)


def get_compound_folder(rootpath, compound):
    fxml = xml.etree.ElementTree.parse(os.path.join(rootpath, compound.get('refid')) + '.xml')
    loc = fxml.getroot()[0].find('location')
    dirname = os.path.basename(os.path.split(loc.get('file'))[0])
    return dirname


def recurse_tree(rootpath, destdir):
    """
    Look for every file in the directory tree and create the corresponding
    ReST files.
    """
    index = xml.etree.ElementTree.parse(os.path.join(rootpath, 'index.xml'))

    for compound in index.getroot():
        if compound.get('kind') not in ALLOWED_TYPES:
            continue
        create_package_file(compound.findtext('name'), compound.get('kind'),
                            compound.get('refid'), get_compound_folder(rootpath, compound),
                            rootpath, destdir)

def get_folders_tree(rootpath):
    tmp = []

    # Retrieve the subfolders indexes
    for root, _, files in os.walk(rootpath):
        for xmlfile in files:
            if not xmlfile.startswith('dir_'):
                continue
            tmp.append(xmlfile)

    # Iterate on them
    dirs = []
    for xmlfile in tmp:
        data = xml.etree.ElementTree.parse(os.path.join(rootpath, xmlfile))
        if not data:
            continue
        for compound in data.getroot():
            name = compound.findtext('compoundname')
            dirs.append(name)

    return dirs


def main():
    rootpath = './doxygen-out/xml'
    destdir = './source/api'

    if not os.path.exists(destdir):
        os.makedirs(destdir)

    dirs = sorted(get_folders_tree(rootpath))
    source_root = dirs[0]
    source_dirs = dirs[1:]
    out_dirs = [os.path.basename(d) for d in dirs]

    # TODO Handle only one level subfolders
    for key in out_dirs:
        ddir = os.path.join(destdir, key)
        if not os.path.exists(ddir):
            os.makedirs(ddir)
        create_modules_toc_file(key, key.capitalize(), destdir)
    recurse_tree(rootpath, destdir)


# So program can be started with "python -m breathe.apidoc ..."
if __name__ == "__main__":
    main()