#!/usr/bin/perl
# ------------------------------------------------------------------------
# $Id: makedoc,v 1.2 2004/02/23 02:46:17 topia Exp $
# ------------------------------------------------------------------------
use strict;
use warnings;
use lib qw(main);
use Unicode::Japanese;
use IO::File;
use File::Find;
use Template;
use TiarraDoc;
my $unijp_init = Unicode::Japanese->new;

my $conf_output = 'sample.conf';

my $stdout_charset = 'euc';
my $conf_charset = 'euc';
my $html_charset = 'euc';

if (!-f 'tiarra' || !-d 'main' || !-d 'module') {
    die "run this script on tiarra's directory.\n";
}

mkdir 'doc';

&makeconf;
&makehtml_mods_toc;
&makehtml_mods;
exit;

sub makeconf {
    print "*** Generating $conf_output... ***\n";

    my $unijp = Unicode::Japanese->new;
    my $t = Template->new('doc-src/sample.conf.in');

    foreach my $conf (DocParser::Module->new('doc-src/conf-main.tdoc')->makeconf) {
	print $conf->[0]." : ".$unijp->set($conf->[1])->$stdout_charset."\n";
	$t->expand($conf->[0] => $unijp->set($conf->[2])->$conf_charset);
    }

    # module.pm򸡺
    my @modules;
    find(sub {
	if (-f $_ && $_ =~ m/\.pm$/) {
	    push @modules, $File::Find::name;
	}
    },'module');

    map {
	my @confs = DocParser::Module->new($_)->makeconf;
	foreach my $conf (@confs) {
	    print $conf->[0]." : ".$unijp->set($conf->[1])->$stdout_charset."\n";
	    $t->modules->add(module => $unijp->set($conf->[2])->$conf_charset);
	}
    } sort @modules;

    my $fh = IO::File->new($conf_output,'w');
    $fh->print($t->str);
}

our $classify_modules_CACHE;
sub classify_modules {
    # ټ¹Ԥ顢η̤å夵롣
    if (defined($_ = $classify_modules_CACHE)) {
	return $_;
    }
    
    my $classified = {}; # {롼̾ => [˴ޤޤ⥸塼DocPod]}
    my $classify = sub {
	my $doc = shift;
	
	my $groupname = do {
	    if ($doc->pkg_name =~ m/^(.+?)::/) {
		$1;
	    }
	    else {
		'';
	    }
	};
	
	my $vec = $classified->{$groupname};
	if (!defined $vec) {
	    $vec = $classified->{$groupname} = [];
	}
	push @$vec,$doc;
    };

    # module.pm򸡺
    find(sub {
	if (-f $_ && $_ =~ m/\.pm$/) {
	    my $parser = DocParser->new($_);
	    my $doc = eval {
		$parser->getdoc;
	    }; if ($@) {
		die "ERROR[$_]: $@\n";
	    }

	    # ʬ
	    $classify->($doc) if defined $doc;
	}
    },'module');

    # 
    foreach (keys %$classified) {
	@{$classified->{$_}} = 
	    map { $_->[1] } 
		sort { $a->[0] cmp $b->[0] }
		    map { [$_->pkg_name, $_]; } @{$classified->{$_}};
    }

    $classify_modules_CACHE = $classified;
    $classified;
}

sub makehtml_mods {
    # եϥ롼˺ա
    # ʤޤǽƤΥ⥸塼򥰥롼פʬहɬפ롣
    my $classified = &classify_modules; # {롼̾ => [˴ޤޤ⥸塼DocPod]}

    mkdir 'doc/module';

    my $unijp = Unicode::Japanese->new;
    my $t = Template->new('doc-src/contents.html');

    while (my ($groupname,$docpods) = each %$classified) {
	my $group_path =
	    join('',
		 'module/',
		 $groupname eq '' ? 'UNCLASSIFIED' : $groupname,
		 '.html');
	print "*** Generating doc/$group_path... ***\n";

	$t->reset;
	$t->expand(
	    group_name => $groupname,
	    css_path => '../default.css',
	);

	my $last_docpod = $docpods->[-1];
	foreach my $docpod (@$docpods) {
	    print "  parsing and translating ".$docpod->pkg_name."\n";
	    # ԤϤΤޤ޽ϡ
	    # key: valueιԤϡ<span id="key"><span id="value">ǽϡ
	    # keyƬ'-'դƤ顢ñˤ'-'ä
	    #
	    # '#'ǻϤޤԤϡ<p id="comment">ǽϤ뤬ʲüʥ롼˽
	    # 1. '#'ιԤϢ³Ƥ硢ιԤĤΥ롼פˤޤȤ롣
	    # 2. ƥ롼'#'˸³붦̤οΥڡ
	    # 3. 塢'#'˥ڡޤĤäƤʤ顢&nbsp;ִ롣
	    #
	    # :
	    # # foo
	    # # bar {
	    # #   baz
	    # # }
	    # 
	    # <p id="comment">
	    #   foo<br />
	    #   bar {<br />
	    #   &nbsp;&nbsp;baz<br />
	    #   }<br />
	    # </p>
	    my $html = ''; # ʸɤUTF-8
	    
	    my @lines = split /\n/,$docpod->content;
	    for (my $i = 0; $i < @lines; $i++) {
		my $line = $lines[$i];

		if ($line eq '') {
		    #$html .= "<br />\n";
		}
		elsif ($line =~ m/^\s*#/) {
		    # 롼׺
		    my @group;
		    for (; $i < @lines; $i++) {
			if ($lines[$i] =~ m/^\s*#/) {
			    # ϥ֥å³
			    (my $stripped = $lines[$i]) =~ s/^\s*#//;
			    
			    # ֤4ĤΥڡѴưϸǽ뤫Τʤ
			    $stripped =~ s/\t/    /g;
			    
			    push @group,$stripped;
			}
			else {
			    $i--;
			    last; # ǽ
			}
		    }
		    
		    # ̤ƬΥڡʤƹԤˤĤƬΥڡθĿ
		    # κǾͤ٤ڡοȤ롣
		    my $spaces_to_remove;
		    foreach (@group) {
			m/^(\s*)/;
			if (defined $1) {
			    my $n_spaces = length($1);
			    if (defined $spaces_to_remove) {
				$spaces_to_remove = $n_spaces
				    if $spaces_to_remove > $n_spaces;
			    }
			    else {
				$spaces_to_remove = $n_spaces;
			    }
			}
		    }
		    if (defined $spaces_to_remove) {
			@group = map {
			    s/^\s{$spaces_to_remove}//; $_;
			} @group;
		    }

		    # ǤĤäƤƬΥڡ&nbsp;ִ
		    @group = map {
			s/^(\s+)/'&nbsp;' x length($1) if defined $1/e; $_;
		    } @group;

		    $html .= qq{<p class="comment">\n};
		    $html .= join('',
				  map {
				      "$_<br />\n";
				  } @group);
		    $html .= qq{</p>\n};
		}
		elsif ($line =~ m/^-?(.+?)\s*:\s*(.*)$/) {
		    my ($key,$value) = ($1,$2);
		    $html .= qq{<span class="key">$key</span>:<span class="value">$value</span><br />\n};
		} elsif ($line =~ m/^(.+?)\s*{\s*$/) {
		    $html .= qq{<span class="key">$1</span>\n};
		    $html .= qq{<div class="block">\n};
		} elsif ($line =~ m/^}\s*$/) {
		    $html .= qq{</div>\n};
		}
	    }

	    # ƥץŸ
	    $t->element->expand(
		content_name => $docpod->pkg_name,
		description => $unijp->set($docpod->header('info'))->$html_charset,
		content => $unijp->set($html)->$html_charset);

	    # 줬ǸǤǤʤСhrɲä롣
	    if ($docpod != $last_docpod) {
		$t->element->hr->add;
	    }

	    $t->element->add;
	}

	# ե˽
	my $fh = IO::File->new("doc/$group_path",'w');
	$fh->print($t->str);
    }
}

sub makehtml_mods_toc {
    print "*** Generating doc/module-toc.html... ***\n";

    my $t = Template->new('doc-src/module-toc.html');

    my $classified = &classify_modules; # {롼̾ => [˴ޤޤ⥸塼DocPod]}

    # module-group.tdocɤǡƥ롼פ롣
    my $groups = DocParser->new('doc-src/module-group.tdoc');

    foreach my $groupname (sort {$a cmp $b} keys %$classified) {
	my $description = do {
	    # Υ롼פФơƤ뤫
	    my $groupdoc = $groups->getdoc($groupname);
	    if (defined $groupdoc) {
		my $description = $groupdoc->header->{description};
		defined $description ? $description : '';
	    }
	    else {
		'';
	    }
	};
	if ($description eq '') {
	    warn "group $groupname don't have description.";
	}

	my $unijp = Unicode::Japanese->new;

	my $group_path =
	    join('',
		 'module/',
		 $groupname eq '' ? 'UNCLASSIFIED' : $groupname,
		 '.html');
	
	$t->toc_group->expand(
	    group_path => $unijp->set($group_path)->$html_charset,
	    group_name => $unijp->set($groupname)->$html_charset,
	    description => $unijp->set($description)->$html_charset,
	);

	# ƥ⥸塼̾ȤŸ
	foreach my $moddoc (@{$classified->{$groupname}}) {
	    print $moddoc->pkg_name." belongs to the group `".$groupname."'\n";
	    $t->toc_group->toc_individual->add(
		group_path => $unijp->set($group_path)->$html_charset,
		mod_name => $unijp->set($moddoc->pkg_name)->$html_charset,
		description => $unijp->set($moddoc->header->{info} || '')->$html_charset,
	    );
	}

	$t->toc_group->add;
    }

    my $fh = IO::File->new('doc/module-toc.html','w');
    $fh->print($t->str);
}
