
# Generate the documentation file

use config;
use gene::common;
use gene::natives;
use gene::replace;
use gene::ToRakuConversions;

# $api : The Qt API description (the output of the parser with the black and
# white info marks added)
# %exceptions : Exceptions if any
sub doc_generator(API :$api, :%exceptions) is export
{
    my %c = $api.qclasses;

    say "";
    say "Generate the documentation : start";
    # say "\n" x 2;


    # Generate the title of the document

    my $title = MODNAME;
    my Str $out =   "$title\n" ~ ('=' x $title.chars) ~ "\n\n";

    $out ~= "Qt classes implemented by "
             ~ MODNAME ~ " V" ~ MODVERSION ~ "\n";
    $out ~= "generated by RaQt_maker V{GENEVERSION}\n\n";

    my $tocTitle = "Table of content:";
    $out ~= "$tocTitle\n" ~ ('-' x $tocTitle.chars) ~ "\n\n";

    spurt TITLEFILE, $out;


    # Generate the core of the document

    $out = "\n";

    for %c.keys.sort -> $k {
        my $v = %c{$k};

        next if !$v.whiteListed || $v.blackListed;
        next if $v.name (elem) $specialClasses;

        # $k (eq $v.name) is the Qt class name
        my $title = "Class $k";
        $out ~= "\n$title\n" ~ ('-' x $title.chars) ~ "\n";
        
        # Print out the "use" intruction
        $out ~= "\timported by\n";
        $out ~= "\t\tuse {MODNAME}::$k;\n\n"; 

        # Print out the parents of the current class
        for $v.parents.sort -> $p {
            $out ~= "\tinherits $p\n";
        }
        $out ~= "\n";

        # Print out the children of the current class
        my $first = True;
        for $v.children.sort -> $c {
            next if !%c{$c}.whiteListed || %c{$c}.blackListed;
            next if $c (elem) $specialClasses;
            if $first {
                $first = False;
                $out ~= "\tinherited by $c";
            } else {
                $out ~= ", $c";
            }
        }
        $out ~= "\n\n";

        # Print out enums if any
        $out ~= showEnums $v;


        $out ~= "\n";


        class KnownMethods {
            has Function $.meth;    # Method
            has Str      $.from;    # Class where method is defined
        }

        # Gather methods
        my @mlist;
        MLOOP0: for $v.methods -> $m {
            next MLOOP0 if !$m.whiteListed || $m.blackListed;
            @mlist.push(KnownMethods.new(meth => $m, from => Str));
        }
        for $v.ancestors -> $a {
            MLOOP1: for %c{$a}.methods -> $m {
                next MLOOP1 if !$m.whiteListed || $m.blackListed;
                @mlist.push(KnownMethods.new(meth => $m, from => $a));
            }
        }


        # Loop on methods
        MLOOP: for @mlist.sort: { .meth.name } -> $mth {

            my $m = $mth.meth;
            my $methodName = $m.name;

            if $m.name ~~ "ctor" {
                if $mth.from {
                    next MLOOP;     # Ctors are not inherited
                } else {
                    $methodName = $k;
                }
            }

            my $qualifiers = "";
            if $m.isSlot {
                $qualifiers ~= "[slot] ";
            }

            if $m.isSignal {
                if $m.isPrivateSignal {
                    $qualifiers ~= "[private signal] "
                } else {
                    $qualifiers ~= "[signal] "
                }
            }

            if $m.isVirtual {
                $qualifiers ~= "[virtual] ";
            }

            if $m.isStatic {
                $qualifiers ~= "[static] ";
            }

            if $m.isProtected {
                $qualifiers ~= "[protected] ";
            }

            if $mth.from {
                $qualifiers ~= "inherited from " ~ $mth.from;
            }

            my $qmeth = qRet($m)  ~ " $methodName"
                        ~ qSignature($m, showDefault => True,
                                    showParenth => True, startWithSep => False);

            if $m.name ~~ "ctor" {
                 $out ~= "#### Method " ~ $k ~ ".new"
                                            ~ strRakuArgsCtorDecl($m, $k, %c);
            } else {
                $out ~= "#### Method " ~ $methodName ~ strRakuArgsDecl($m, %c);
            }

            $out ~= "\n\t" ~ $qualifiers if $qualifiers ne "";
            $out ~= "\n\tcalls Qt method " ~ $qmeth ~ "\n\n";
        }

    }

    spurt DOCFILE, $out;
    
    
    # If hoedown utility is available, build an html documentation file
    # from the markdown files
    
    if (run 'hoedown', '--version', :out).exitcode != 0 {
        say "    hoedown utility not found.";
        say "    Skip making Classes.html from Classes.md";
    } else {

        say "    Convert documentation from MD to HTML:";
        
        # HTML header
        my $html = q:to/END/;
            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
            "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            END

        # HTML document title
        $html ~= (run 'hoedown', '--', TITLEFILE, :out).out.slurp: :close;

        # HTML table of contents
        $html ~= (run 'hoedown', '-t',  '2', '--html-toc',
                                '--', DOCFILE, :out).out.slurp: :close;
        # HTML main part
        $html ~= (run 'hoedown', '-t', '2',
                                '--', DOCFILE, :out).out.slurp: :close;
        # Write the destination html file
        spurt HTMLFILE, $html;
        
        say "    done";
    }    

    say "Generate the documentation : end";
}










