#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Std;
use Locale::PO;
use JSON;
use Encode;

# current limits:
# - we do not support plural. forms
# - no message content support

my $options = {};

getopts('t:o:v:', $options) ||
    die "unable to parse options\n";

die "no files specified\n" if !scalar(@ARGV);

#my $filename = shift || die "no po file specified\n";

# like FNV32a, but we only return 31 bits (positive numbers)
sub fnv31a {
    my ($string) = @_;

    my $hval = 0x811c9dc5;

    foreach my $c (unpack('C*', $string)) {
	$hval ^= $c;
	$hval += (
	    (($hval << 1) ) +
	    (($hval << 4) ) +
	    (($hval << 7) ) +
	    (($hval << 8) ) +
	    (($hval << 24) ) );
	$hval = $hval & 0xffffffff;
    }
    return $hval & 0x7fffffff;
}

my $catalog = {};

foreach my $filename (@ARGV) {
    my $href = Locale::PO->load_file_ashash($filename) ||
	die "unable to load '$filename'\n";
    
    my $charset;
    my $hpo = $href->{'""'} || die "no header";
    my $header = $hpo->dequote($hpo->msgstr);
    if ($header =~ m|^Content-Type:\s+text/plain;\s+charset=(\S+)$|im) {
	$charset = $1;
    } else {
	die "unable to get charset\n" if !$charset;
    }


    foreach my $k (keys %$href) {
	my $po = $href->{$k};
	next if $po->fuzzy(); # skip fuzzy entries
	my $ref = $po->reference();

	# skip unused entries
	next if !$ref;

	# skip entries if t is defined (pve/pmg) and the string is
	# not used there or in the widget toolkit
	next if $options->{t} && $ref !~ m/($options->{t}|proxmox)\-/;
    
	my $qmsgid = decode($charset, $po->msgid);
	my $msgid = $po->dequote($qmsgid);

	my $qmsgstr = decode($charset, $po->msgstr);
	my $msgstr = $po->dequote($qmsgstr);

	next if !length($msgid); # skip header
	
	next if !length($msgstr); # skip untranslated entries

	my $digest = fnv31a($msgid);

	die "duplicate digest" if $catalog->{$digest};

	$catalog->{$digest} = [ $msgstr ];
	# later, we can add plural forms to the array
    }
}

my $json = to_json($catalog, {canonical => 1, utf8 => 1});

my $content = "// $options->{v}\n"; # write version to beginning

my $outfile = $options->{o};

$content .= "// Proxmox Message Catalog: $outfile\n" if $outfile;

$content .= <<__EOD;
__proxmox_i18n_msgcat__ = $json;

function fnv31a(text) {
    var len = text.length;
    var hval = 0x811c9dc5;
    for (var i = 0; i < len; i++) {
	var c = text.charCodeAt(i);
	hval ^= c;
	hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
    }
    hval &= 0x7fffffff;
    return hval;
}

function gettext(buf) {
    var digest = fnv31a(buf);
    var data = __proxmox_i18n_msgcat__[digest];
    if (!data) {
	return buf;
    }
    return data[0] || buf;
}
__EOD

if ($outfile) {
    open(my $fh, '>', $outfile) ||
	die "unable to open '$outfile' - $!\n";
    print $fh $content;
} else {
    print $content;
}
