#!/usr/bin/perl

if ($ARGV[0] eq "-h"){
    $dir = $ARGV[1];
    $html = 1;
    shift @ARGV;
    shift @ARGV;
}

if ($html){
    opendir (D, "$dir/sources/") || die "Can not open $dir";
    while ($n = readdir (D)){
	if ($n =~ /mono-api-.*\.html$/){
	    open (IN, "$dir/sources/$n") || die "Can not open $n";
	    $files[$filecount] = $n;
	    while (<IN>){
		@files_content[$filecount] .= $_;
		if (/name="api:(.*?)"/){
		    $_ =~ s/.*name="api:(\w+?)".*/\1/;
		    $apis[$filecount] .= "$_";
		}
	    }
	    $filecount++;
	    close IN;
	}
    }
}

while (<ARGV>){
	if (/\/\*\* *\n/){
		&process_doc;
	} else {
		#print "IGNORING: $_";
	}
}

if ($html){
    for ($f = 0; $f < $filecount; $f++){
	$name = $files[$f];
	open (OUT, "> $dir/html/$name") || die "Can not create $dir/html/$name";
	print "Merging: $name\n";
	print OUT<<EOF;
<?xml version="1.0" encoding="utf-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <title>$name</title>
   <style type="text/css">
   h3 { 
       font-size: 18px;
       padding-bottom: 4pt;
       border-bottom: 2px solid #dddddd;
   }
       
   .api {
     border: 1px solid;
     padding: 10pt;
     margin: 10pt;
   } 

   .api-entry { 
       border-bottom: none;
       font-size: 18px;
   }

   .prototype {
     border: 1px solid;
     background-color: #f2f2f2;
     padding: 5pt;
     margin-top: 5pt;
     margin-bottom: 5pt;  
   } 

   .header {
     border: 1px solid;
     padding: 0 0 5pt 5pt;
     margin: 10pt;
     white-space: pre;
       font-family: monospace;
   }
    
   .code {
     border: 1px solid;
     padding: 0 0 5pt 5pt;
     margin: 10pt;
     white-space: pre;
       font-family: monospace;
   }
   </style>
</head>
<body>
EOF
	@a = split (/\n/, $files_content[$f]);

	for ($ai = 0; $ai < $#a; $ai++){
	    $line = $a[$ai];
	    
	    ($api,$caption) = $line =~  /<h4><a name=\"api:(\w+)\">(\w+)<\/a><\/h4>/;
	    if ($api ne ""){
		if ($api_shown == 1){
		    print OUT "</div>";
		}
		$api_shown = 1;
		$proto = $prototype{$api};
		if ($proto eq ""){
		    $proto = "Prototype: $api";
		}

print OUT<<EOF;
 <a name="api:$api"></a>
 <div class="api">
    <div class="api-entry">$api</div>

    <div class="prototype">$proto</div>
<p>
EOF
		    &opt_print ("Parameters", $arguments{$api}, 1);
		    &opt_print ("Returns", $returns{$api}, 1);
		    &opt_print ("Remarks", $bodies{$api}, 0);
		    print OUT "\n";
	    } else {
		if ($line =~ /@API_IDX@/){
		    $apis_toc = &create_toc ($apis[$f]);
		    $line =~ s/\@API_IDX\@/$apis_toc/;
		}
		if ($line =~ /^<h/){
		    print OUT "</div>";
		    $api_shown = 0;
		}

		print OUT "$line\n";
	    }
	}
	print OUT<<EOF;
</body>
</html>
EOF
	close OUT;
	system ("$ENV{runtimedir}/mono-wrapper convert.exe $dir/html/$name $dir/html/x-$name");

	# clean up the mess that AgilityPack does, it CDATAs our CSS
	open HACK, "$dir/html/x-$name" || die "Could not open $dir/html/x-$name";
	open HACKOUT, ">$dir/deploy/$name" || die "Could not open output";

	while (<HACK>){
	    s/^\/\/<!\[CDATA\[//;
	    s/^\/\/\]\]>\/\///;
	    print HACKOUT $_;
	}
	#system ("cp.exe $dir/html/$name $dir/deploy/$name");
    }
}

sub process_doc {
	$doc = "";
	$func = <>;
	chop $func;
	$func =~ s/^ \* //;
	$func =~ s/:$//;
	print "Function: $func\n" if (!$html);
	$args = "";
	$inbody = 0;
	$returns = "";
	$body = "";
	$functions[$fn++] = $func;

	# Process arguments
	while (<>){
		if (/^ \*\*?\//){
		    $body =~ s/[@#](\w+)/<i>\1<\/i>/g;
		    $returns =~ s/[@#](\w+)/<i>\1<\/i>/g;

		    $args =~ s/@(\w+)/<i>\1<\/i>/g;
		    $body =~ s/\n/ /;
		    $bodies{$func} = $body;
		    $arguments{$func} = $args;
		    $returns{$func} = $returns;
		    $proto = "";
		    while (<>){
			$proto .= $_;
			last if (/\{/);
		    }
		    $proto =~ s/{//;
		    # clean it up a little, remove newlines, empty space at end
		    $proto =~ s/ +$//;
		    # Turn "Type * xxx" into "Type* xxx"
		    $proto =~ s/^(\w+)\W+\*/\1\*/;
		    $prototype{$func} = $proto;
		    return;
		}
		chop;
		s/^\ \*//;
		$_ = "\n<p>" if (/^\s+$/);
				
		if ($inbody == 0){
		    if (/\s*(\w+):(.*)/){
			$args .= "<dt><i>$1:</i></dt><dd>$2</dd>";
		    } else {
			
			$body = "\t$_\n";
			$inbody = 1;
		    }
		} elsif ($inbody == 1) {
		    if (/Returns?:/){
			s/Returns?://;
			$returns = "\t$_\n";
			$inbody = 2;
		    } else {
			$body .= "\n\t$_";
		    }
		} else {
		    $returns .= "\n\t$_";
		}
		   
	}
}

sub create_toc {
    my ($apis_listed) = @_;
    my $type_size = 0;
    my $name_size = 0;
    my $ret, $xname, $args, $line;
    $apis_toc = "";


    # Try to align things, so compute type size, method size, and arguments
    foreach $line (split /\n/, $apis_listed){
	$p = $prototype{$line};
	($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
	$tl = length ($ret);
	$pl = length ($xname);

	$type_size = $tl if ($tl > $type_size);
	$name_size = $pl if ($pl > $name_size);
    }

    $type_size++;
    $name_size++;

    foreach $line (split /\n/, $apis_listed){
	chop;
	$p = $prototype{$line};
	($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
	
	$rspace = " " x ($type_size - length ($ret));
	$nspace = " " x ($name_size - length ($xname));
	$args = &format ($args, length ($ret . $rspace . $xname . $nspace), 60);
	$apis_toc .= "$ret$rspace<a href=\"\#api:$line\">$xname</a>$nspace$args\n";
    }
    return $apis_toc;
}

#
# Formats the rest of the arguments in a way that will fit in N columns
#
sub format {
    my ($args, $size, $limit) = @_;
    my $sret = "";

#    return $args if ((length (args) + size) < $limit);
    
    $remain = $limit - $size;
    @sa = split /,/, $args;
    $linelen = $size;
    foreach $arg (@sa){
	if ($sret eq ""){
	    $sret = $arg . ", ";
	    $linelen += length ($sret);
	} else {
	    if ($linelen + length ($arg) < $limit){
		$sret .= "FITS" . $arg . ", ";
	    } else {
		$newline = " " x ($size) . $arg . ", ";
		$linelen = length ($newline);
		$sret .= "\n" . $newline;
	    }
	}
    }
    $sret =~ s/, $/;/;
    return $sret;
}

sub opt_print {
    my ($caption, $opttext, $quote) = @_;

    if ($opttext ne "" && (!($opttext =~ /^[ \t]+$/))){
	print OUT "<b>$caption</b>\n";
	if ($quote == 1){
	    print OUT "<blockquote>$opttext</blockquote>\n";
	} else {
	    print OUT "<p>$opttext\n";
	}
    }
}
