#!/usr/bin/perl

use warnings;
use strict;
use Getopt::Long;
use POSIX;
use Encode;

our $VERSION=1.0;
our $tagname='gt';

our 
(
 $htmlcharset, # html charset
 $html,        # input file name
 $output,      # output file name
 $po,          # po-file
)=('UTF-8');

sub usage()
{
  print <<usagetext;
Usage: 
  $0 [OPTIONS] [ -p lang.po ] [ -o out.html ] input.html

OPTIONS:
  -p filename         - name PO-file for generate lang.html;
  -o filename         - name output-file (default use STDOUT);
  -tag tagname        - tagname for mark gettext (default 'gt');
  -charset name       - html charset (default: UTF-8).

usagetext
  exit -1;
}

sub readpo()
{
  defined $po or return ();
  -r $po or die "Can not find file '$po'";

  open my $file, '<', $po or die "Can not open file '$po': $!";

  my ($rec, @records)=('',);

  while(<$file>)
  {
    s/^\s+//; s/\s+$//;
    
    if ($_ eq '')
    {
      length $rec and push @records, $rec;
      $rec='';
    }
    $rec .= "$_\n";
  }

  length $rec and push @records, $rec;

  for (my $i=$#records; $i>=0; $i--)
  {
    defined $records[$i] and $records[$i]=~/\S/s and next;
    splice @records, $i, 1;
  }

  my $lineno=1;
  for $rec (@records)
  {
    my $flags='';
    my ($msgid, $msg);
    my @lines=split /\n/, $rec;
    s/\s+$// for @lines;

    for (@lines)
    {
      /^#,\s*(.*)/ and $flags .= " $1";
      /^#/ and $lineno++, next;
      /^$/ and $lineno++, next;
      
      if (/^msgid\s+"(.*)"/)
      {
        defined $msgid and 
          die "msgid already defined: $msgid ($_)\nline: $lineno\n";
        $msgid=$1;
        $lineno++;
        next;
      }
      defined $msgid or 
        die "msgid not defined: $_\nline: $lineno\n";

      if (/^msgstr\s+"(.*)"/)
      {
        defined $msg and 
          die "msgstr already defined: $msg ($_)\nline: $lineno\n";
        $msg=$1;
        $lineno++;
        next;
      }
      defined $msg or 
        die "msgstr not defined: $_\nline: $lineno";

      /^"(.*)"$/ or die "Unknown format line: $_\nline: $lineno\n";
      $msg .= "\n$1";

      $lineno++;
    }

    defined $msgid and 
      $msgid=~s/\\"/"/g, 
      $msgid=~s/\\\\/\\/g;
    defined $msg and 
      $msg=~s/\\n/\n/g, 
      $msg=~s/\\r/\r/g,
      $msg=~s/\\t/\t/g,
      $msg=~s/\\a/\a/g,
      $msg=~s/\\(\S)/$1/g;


    $rec={flags=>$flags, msgid=>$msgid, msgstr=>$msg};
#     print STDERR $rec->{msgid}, "\n";
  }
  
  for (my $i=$#records; $i>=0; $i--)
  {
    unless (defined $records[$i]->{msgid} and 
        defined $records[$i]->{msgstr})
    {
      splice @records, $i, 1;
    }
  }
  return @records;

}

GetOptions
(
  'p=s'         => \$po,
  'o=s'         => \$output,
  'tag=s'       => \$tagname,
  'charset=s'   => \$htmlcharset,
) or usage;
$html=$ARGV[0] or usage;
-r $html or die "Can not find file '$html'";

my $data;
{
  open my $file, '<', $html or die "Can not open file '$html': $!";
  local $/;
  $data=<$file>;
}

if (defined $output)
{
  open my $file, '>', $output or die "Can not open file '$output': $!";
  POSIX::dup2(fileno($file), fileno(STDOUT));
}

my @blocks=split /<\s*$tagname\s*>.*?<\s*\/$tagname\s*>/is, $data;
my @tags=$data=~/<\s*$tagname\s*>\s*(.*?)\s*<\s*\/$tagname\s*>/isg;
s/\s+/ /sg, s/^\s//, s/\s$// for @tags;

my @poary=readpo;
print STDERR "Found ", scalar(@poary), " message blocks\n";
my $charset='UTF-8';

for (@poary)
{
  $_->{msgid} eq '' or next;
  $_->{flags} =~ /fuzzy/ and next;
  $_->{msgstr} =~ /Content-Type:\s*\w+\/\w+\s*;\s*charset=\s*(\S+)/si or next;
  $charset=$1;
}

while(@blocks)
{
  print shift @blocks;
  my $tag=shift @tags;
  defined $tag or next;
  

  my $tagnew;
  for my $potag (@poary)
  {
    $potag->{flags}=~/fuzze/ and next;
    if ($potag->{msgid} eq $tag)
    {
      length $potag->{msgstr} or next;
      $tagnew=$potag->{msgstr};
      $tagnew=Encode::decode($charset, $tagnew, Encode::FB_CROAK);
      $tagnew=Encode::encode($htmlcharset, $tagnew, Encode::FB_CROAK);
    }
  }
  

  unless (defined $tagnew)
  {
    $tagnew=$tag;
    print STDERR "Found '$tag' ... FAILED\n";
  }

  print $tagnew;
}

