#! /usr/bin/perl

use W_cache;
use Jcode;
use Getopt::Std;

our($opt_i, $opt_o, $opt_g, $opt_l);
getopts('i:o:g:l');

# parse header info
if ($opt_l) {
    while($file = shift(@ARGV)) {
	if (-f $file) {
	    my $cache = W_cache->new("$file");
	    if (defined $cache) {
		$cache->parse_header();
		printf "Cache ver.: %08x\n", $cache->c_ver;
		printf "name len.: %d\n", $cache->n_len;
		print jcode($cache->f_name, 'sjis')->euc, "\n";
		print "size: ", $cache->f_size, " bytes.\n";
		my $b_num = $cache->b_num;
		my @dmap = unpack "C*", $cache->dmap;
		my @a = grep(/1/, @dmap);
		if ($b_num) {
		    print "b_num: $b_num\n";
		    printf "%.1f %\n", (($#a+1)/$b_num)*100;
		}
		#for (my $i=0; $i<=$#dmap; $i++) {
		#    printf "%d ", $dmap[$i];
		#    print "\n" if $i % 32 == 31;
		#}
		#print "\n";
		printf "ref num.: %d\n", $cache->b_ref;
		printf "file mtime: %d\n", $cache->mtime;
		my $md5 = $cache->file_md5;
		my $pmd5 = unpack("H32", $md5);
		print "File md5: $pmd5\n";
		printf "Fn =? %s\n", unpack("H32", $md5 ^ $W_cache::FN_KEY);
		print "trip:\n"; hexdump($cache->trip);
		print "\n";
		printf "up flag: %02x\n", $cache->upflag;
		printf "bbs flag: %02x\n", $cache->bbsflag;
		print "head length: " . $cache->head_size . "\n";
	    }
	}
    }
    exit(0);
}


# convert cache file -> file
if ( "$opt_i" ) {
    my $ca = W_cache->new("$opt_i");
    my $f_mane = '';
    if (defined $ca) {
	$ca->parse_header();
	my $b_num = $ca->b_num;
	$f_name = $ca->f_name;
	my @dmap = unpack "C*", $ca->dmap;
	my @a = grep(/1/, @dmap);
	if ($b_num) {
	    print "b_num: $b_num\n";
	    printf "%.1f %\n", (($#a+1)/$b_num)*100;
	    if ($#a+1 == $b_num) { # 100%
		;
	    } else {
		die "cache file $opt_i is incomplete\n";
	    }
	}
	if ($opt_o) {
	    $f_name = "$opt_o";
	}
	open OUT, ">$f_name"
	    or die "can't open $f_name: $!\n";
	$ca->bulk_conv(*OUT);
	close(OUT);

    } else {
	print "can't parse $opt_i\n";
    }
    exit(0);
}

# convert file -> cache file
if ( "$opt_g" ) {
    if (-f "$opt_g") {
	my $cache = W_cache->new("$opt_g",
				 Encode   => 1);
	if (defined $cache) {
	    $cache->bulk_encode();
	    $cache->decode_header();
	    printf "Cache ver.: %08x\n", $cache->c_ver;
	    printf "name len.: %d\n", $cache->n_len;
	    print jcode($cache->f_name, 'sjis')->euc, "\n";
	    print "size: ", $cache->f_size, " bytes.\n";
	    my $b_num = $cache->b_num;
	    my @dmap = unpack "C*", $cache->dmap;
	    my @a = grep(/1/, @dmap);
	    if ($b_num) {
		print "b_num: $b_num\n";
		printf "%.1f %\n", (($#a+1)/$b_num)*100;
	    }
	    #for (my $i=0; $i<=$#dmap; $i++) {
	    #    printf "%d ", $dmap[$i];
	    #    print "\n" if $i % 32 == 31;
	    #}
	    #print "\n";
	    printf "ref num.: %d\n", $cache->b_ref;
	    printf "file mtime: %d\n", $cache->mtime;
	    my $md5 = $cache->file_md5;
	    my $pmd5 = unpack("H32", $md5);
	    print "File md5: $pmd5\n";
	    printf "Fn =? %s\n", unpack("H32", $md5 ^ $W_cache::FN_KEY);
	    print "trip:\n"; hexdump($cache->trip);
	    print "\n";
	    printf "up flag: %02x\n", $cache->upflag;
	    printf "bbs flag: %02x\n", $cache->bbsflag;
	    print "head length: " . $cache->head_size . "\n";

	}
    }
    exit(0);
}

sub hexdump {
    my ($str) = @_;

    my @dat = unpack('C*', $str);
    my $len = $#dat;

    my ($i, $j) = (0, 0);
    while ($j <= $len) {
        print "=";
        for ($i=0; $i<16; $i++) {
            last if ($j+$i > $len);
            printf " %02x", $dat[$j+$i];
        }
        print "   " x (16-$i);
        print "  ";
        for ($i=0; $i<16; $i++) {
            last if ($j+$i > $len);
            my $c = $dat[$j+$i];
            printf "%c", (($c<0x20||$c>0x7f) ? ord(".") : $c);
        }
        $j+=$i;
        print "\n";
    }
}
