#! /usr/bin/perl -w
########################################################################

use strict;
use utf8;
use locale;
use POSIX qw(locale_h);
use POSIX qw(strftime);
use Encode 'from_to','encode_utf8','decode_utf8';
use English;
use Getopt::Long;
use File::Path;
use XML::Parser;
use Data::Dumper;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";
binmode STDERR, ":utf8";

#----------------------------------------------------------------------
# global variables

my $version = "0.20100514";

my $original_wd;
chomp ($original_wd = `pwd`);

my @handoffFiles = ();
my %handoffXmlTrees = ();

my $totalNumberOfIdsNotFoundInSpec = 0;
my $totalNumberOfIdsLackingEngineeringEnglish = 0;

my $class;

my $OPT_VERBOSITY;
my $OPT_VERSION;
my $OPT_HELP;
my $OPT_EEDIR;
my $OPT_HANDOFF_URL;
my $OPT_HANDOFF_DIR;
my $OPT_HTTP_USER;
my $OPT_HTTP_PASSWD;
my $OPT_SKIP_DOWNLOAD;
my $OPT_OUTPUTDIR;

# engineering English packages which should be ignored because they are obsolete:
my @engineeringEnglishPackagesObsolete = (
    "libdui-l10n-engineering-english", # now "libmeegotouch-l10n-engineering-english"
    "duistartup-l10n-engineering-english", # now "mstartup-l10n-engineering-english"
    "dui-demos-widgetsgallery-l10n-engineering-english" # now "meegotouch-demos-widgetsgallery-l10n-engineering-english"
    );

# engineering English packages which should be ignored because they are only demos:
my @engineeringEnglishPackagesIgnore = (
    "meegotouch-demos-widgetsgallery-l10n-engineering-english",
    "duihomescreen-plugins-weatherapplet-l10n-engineering-english"
    );

my @engineeringEnglishPackages = (
    "account-plugin-att-l10n-engineering-english",
    "account-plugin-facebook-l10n-engineering-english",
    "account-plugin-google-l10n-engineering-english",
    "account-plugin-ovi-l10n-engineering-english",
    "account-plugin-youtube-l10n-engineering-english",
    "accounts-ui-l10n-engineering-english",
    "activities-l10n-engineering-english",
    "backup-framework-l10n-engineering-english",
    "call-history-l10n-engineering-english",
    "call-ui-l10n-engineering-english",
    "camera-ui-l10n-engineering-english",
    "cellular-adaptation-ui-l10n-engineering-english",
    "commhistory-daemon-l10n-engineering-english",
    "conn-dui-bluetooth-l10n-engineering-english",
    "conn-dui-cellular-l10n-engineering-english",
    "conn-dui-internet-l10n-engineering-english",
    "conn-dui-wlan-l10n-engineering-english",
    "contacts-l10n-engineering-english",
    "crash-reporter-l10n-engineering-english",
    "devicelock-l10n-engineering-english",
    "dialer-l10n-engineering-english",
    "dui-demos-widgetsgallery-l10n-engineering-english",
    "duicontrolpanel-callandsimapplet-l10n-engineering-english",
    "duicontrolpanel-certificatesapplet-l10n-engineering-english",
    "duicontrolpanel-datetimeapplet-l10n-engineering-english",
    "duicontrolpanel-displaylanguageapplet-l10n-engineering-english",
    "duicontrolpanel-keyboardlanguageapplet-l10n-engineering-english",
    "duicontrolpanel-l10n-engineering-english",
    "duicontrolpanel-networkapplet-l10n-engineering-english",
    "duicontrolpanel-regionformatapplet-l10n-engineering-english",
    "duicontrolpanel-skeletonapplet-l10n-engineering-english",
    "duihelp-l10n-engineering-english",
    "duihomescreen-l10n-engineering-english",
    "duihomescreen-plugins-weatherapplet-l10n-engineering-english",
    "duistartup-l10n-engineering-english",
    "duistatusind-connectivity-l10n-engineering-english",
    "feedreader-l10n-engineering-english",
    "gallery-l10n-engineering-english",
    # file conflict with accounts-ui-l10n-engineering-english
    # "keychain-ui-l10n-engineering-english",
    "libdatacounterdialog-l10n-engineering-english",
    "libdialerui-l10n-engineering-english",
    "libfeedsettings-l10n-engineering-english",
    "liblocationpicker-l10n-engineering-english",
    "libmcontentwidgets-l10n-engineering-english",
    "libmeegotouch-l10n-engineering-english",
    "libpresence0-l10n-engineering-english",
    "libshare-ui-l10n-engineering-english",
    "libwebupload-l10n-engineering-english",
    "location-ui-l10n-engineering-english",
    "locationsettings-l10n-engineering-english",
    "me-l10n-engineering-english",
    "meegotouch-demos-widgetsgallery-l10n-engineering-english",
    "messaging-ui-l10n-engineering-english",
    "mms-ui-l10n-engineering-english",
    "mstartup-l10n-engineering-english",
    "office-tools-l10n-engineering-english",
    "package-manager-l10n-engineering-english",
    "package-manager-ui-l10n-engineering-english",
    # file conflict with accounts-ui-l10n-engineering-english
    # "signon-ui-l10n-engineering-english",
    "systemui-applets-l10n-engineering-english",
    "systemui-l10n-engineering-english",
    "transfer-ui-l10n-engineering-english",
    "webupload-engine-l10n-engineering-english"
    );

#----------------------------------------------------------------------
# subroutines:

sub usage {
    printf STDERR "Usage: photo-gallery [option] ...\n";
    printf STDERR "-v, --verbose           print some progress messages to standard output.\n";
    printf STDERR "    --version           display version and exit.\n";
    printf STDERR "-h, --help              display this help and exit.\n";
    printf STDERR "    --eedir             directory where the ee .qm files are.\n";
    printf STDERR "    --handoffurl        URL of the “handoff” .ts files.\n";
    printf STDERR "    --handoffdir        directory to save the “handoff” .ts files.\n";
    printf STDERR "    --http-user         user name to access the “handoff” .ts files.\n";
    printf STDERR "    --http-passwd       password to access the “handoff” .ts files.\n";
    printf STDERR "                        or use .netrc to store user name and password.\n";
    printf STDERR "    --skip-dowload      skip download.\n";
    printf STDERR "    --output-dir        directory to write the output files to.\n";
    printf STDERR "                        default is ./messageid-check-results/\n";
    exit 1;
}

sub mySystem {
    my ($command) = @_;
    if ($OPT_VERBOSITY >= 1) {
        print "executing: $command\n";
    }
    return system ($command);
}

sub myExit {
    my ($value) =@_;
    chdir $original_wd || die "Can’t cd to $original_wd: $!\n";
    exit ($value);
}

sub myBasename {
    my ($path) =@_;
    $path =~ /\/([^\/]+)$/; # basename (strip directory)
    return $1;
}

sub writeHtml {
    my ($htmlOutBody) =@_;
    my $date = decode_utf8(`date`);
    chomp($date);
    my $title = "Results of messageid-check (version $version) run on " . $date;

    my $htmlOutHeader = "";
    $htmlOutHeader .= <<"EOF";
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
<html>
<head>
<title>$title</title>
<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">
<style type=\"text/css\">
body {
  color:#000000;
  background-color:#FFFFFF;
  font-family: sans-serif;
  font-size: 1em;
}
.okcolor {
  color:#00FF00;
}
.errorcolor {
  color:#FF0000;
}
.okbgcolor {
  background-color:#ceeebc;
}
.errorbgcolor {
  background-color:#ffcdcd;
}
.eefile {
  border: solid 1px #88c3ff;
  margin-bottom: 10px;
}
.title {
  background-color: #5a9fe5;
  font-weight: bold;
  padding: 5px;
  padding-left: 15px;
  font-size: 20px;
}
.package {
  background-color: #71b1f2;
  font-weight: bold;
  padding: 5px;
  padding-left: 15px;
  font-size: 20px;
}
table.summary {
  text-align: right;
  font-style: normal;
  font-size: small;
  border: 1;
  margin-top: 0em;
  margin-bottom: 0em;
  margin-left: 0em;
  margin-right: 0em;
  padding-top: 1em;
  padding-bottom: 1em;
  padding-left: 0em;
  padding-right: 0em;
  clear: left;
}
table.summary td {
  color: #000000;
  padding-top: 0em;
  padding-bottom: 0em;
  padding-left: 0.5em;
  padding-right: 0.5em;
}
.maintainer {
  text-align: right;
  font-size: 20px;
  background-color: #88c3ff;
  padding-right: 20px;
  padding-bottom: 1px;
}
.errorlist {
  text-align: left;
  background-color: #ffcdcd;
  padding-left: 20px;
  padding-top: 20px;
  padding-bottom: 1px;
}
.oklist {
  text-align: left;
  background-color: #ceeebc;
  padding-left: 20px;
  padding-top: 20px;
  padding-bottom: 1px;
}
</style>
</head>
<body>
<h1>$title</h1>
EOF

    my $htmlOutFooter = "";
    $htmlOutFooter .= <<"EOF";
</body>
</html>
EOF

    my $htmlOutTotal = $htmlOutHeader . $htmlOutBody . $htmlOutFooter;

    open (HTML, ">$OPT_OUTPUTDIR/messageid-check-result.html") || die "can't open file $OPT_OUTPUTDIR/messageid-check-result.html: $!";
    binmode HTML, ":utf8";
    printf HTML "%s", $htmlOutTotal;
    close (HTML);

}

sub download {
    if (mySystem("fakeroot apt-get update")) {
        printf (STDERR "“fakeroot apt-get update” didn’t work.\n");
        exit (1);
    }

    for my $engineeringEnglishPackage (@engineeringEnglishPackages) {
        if (mySystem("fakeroot apt-get -y --force-yes install $engineeringEnglishPackage")) {
            printf (STDERR "“fakeroot apt-get -y --force-yes install $engineeringEnglishPackage” didn’t work.\n");
            exit (1);
        }
        else {
            printf (STDOUT "“fakeroot apt-get -y --force-yes install $engineeringEnglishPackage” OK.\n");
        }
    }

    if (-d "$OPT_HANDOFF_DIR") {
        rmtree ("$OPT_HANDOFF_DIR", {verbose => 1});
    }
    mkdir ("$OPT_HANDOFF_DIR") || die "Can’t mkdir $OPT_HANDOFF_DIR: $!\n";
    chdir ("$OPT_HANDOFF_DIR") || die "Can’t cd to $OPT_HANDOFF_DIR: $!\n";

    my $wgetCommand = "wget -nd -r -l1 ";
    if ($OPT_HTTP_USER ne "") {
        $wgetCommand .= "--http-user=$OPT_HTTP_USER ";
    }
    if ($OPT_HTTP_PASSWD ne "") {
        $wgetCommand .= "--http-passwd=$OPT_HTTP_PASSWD ";
    }
    $wgetCommand .= "$OPT_HANDOFF_URL";

    if (mySystem($wgetCommand)) {
        printf (STDERR "“wget $OPT_HANDOFF_URL” didn’t work.\n");
        myExit (1);
    }

    chdir $original_wd || die "Can’t cd to $original_wd: $!\n";

    @handoffFiles = glob ("$OPT_HANDOFF_DIR/*.ts");
    if ($#handoffFiles < 0) {
        printf (STDERR "download of handoff .ts files failed.\n");
        myExit(1);
    }

    # Convert handoff files mac2unix:
    for my $file (@handoffFiles) {
        printf(STDOUT "mac2unix %s\n", $file);
        my $fileContents = "";
        open (TS, "<:encoding(UTF-8)", "$file") || die "Can’t open file $file: $!";
        while(<TS>) {
            $ARG =~ s/\x{FEFF}//; # remove BOM
            $ARG =~ s/\r/\n/gi;   # replace returns with newlines
            $fileContents .= $ARG;
        }
        close (TS);
        open (TS, ">:encoding(UTF-8)", "$file") || die "Can’t open file $file: $!";
        printf(TS "%s", $fileContents);
        close (TS);
    }
}

sub findEngineeringEnglishFiles {
    my %engineeringEnglishPackages = ();
    for my $package (@engineeringEnglishPackages) {
        if (grep(/^${package}$/, @engineeringEnglishPackagesObsolete)
            || grep(/^${package}$/, @engineeringEnglishPackagesIgnore)) {
            if ($OPT_VERBOSITY >=1) {
                printf (STDOUT "ignoring %s\n", $package);
            }
        }
        else {
            $engineeringEnglishPackages{$package} = "";
        }
    }
    @engineeringEnglishPackages = (sort (keys %engineeringEnglishPackages));
    my @engineeringEnglishFiles = ();
    for my $package (@engineeringEnglishPackages) {
        if ($OPT_VERBOSITY >= 1) {
            printf (STDOUT "using %s\n", $package);
        }
        my @qmFiles = grep (/\.qm$/, qx(dpkg -L $package));
        if ($#qmFiles < 0) {
            printf (STDOUT "ERROR: %s has no .qm files.\n", $package);
            exit (1);
        }
        else {
            for my $file (@qmFiles) {
                chomp ($file);
                if ($OPT_VERBOSITY >= 1) {
                    printf (STDOUT "    %s\n", $file);
                }
                push (@engineeringEnglishFiles, $file);
            }
        }
    }
    return @engineeringEnglishFiles;
}

sub readHandoffXmlTrees {
    for my $handoffFile (glob ("$OPT_HANDOFF_DIR/*.ts")) {
        my $xmlParser = new XML::Parser(Style => 'Tree', ProtocolEncoding => 'UTF-8');
        if ($OPT_VERBOSITY >= 1) {
            printf STDOUT "parsing %s\n", $handoffFile;
        }
        $handoffXmlTrees{$handoffFile} = $xmlParser->parsefile($handoffFile);
    }
}

sub checkMessageIdFromSourceAgainstHandoff {
    my ($engineeringEnglishFile, $eeMessageId, $htmlOutRef) = @_;
    my $eeMessageIdIsInSpecCount = 0;

    for my $handoffFile (@handoffFiles) {
        my $tree = $handoffXmlTrees{$handoffFile};
        my @tsTree = @{$tree->[1]};
        # print Dumper(@tsTree);
        my $extra_application_info = "";
        my $extra_ui_spec_document = "";
        my $extra_ts_date = "";
        my $extra_ts_macroversion = "";
        my @contextTree = ();
        for (my $i = 0; $i < $#tsTree; ++$i) {
          SWITCH: {
              if ($tsTree[$i] eq "extra-application-info") {
                  $extra_application_info = $tsTree[$i+1][2];
                  last SWITCH;
              }
              if ($tsTree[$i] eq "extra-uispec-document") {
                  $extra_ui_spec_document = $tsTree[$i+1][2];
                  last SWITCH;
              }
              if ($tsTree[$i] eq "extra-ts-date") {
                  $extra_ts_date = $tsTree[$i+1][2];
                  last SWITCH;
              }
              if ($tsTree[$i] eq "extra-ts-macroversion") {
                  $extra_ts_macroversion = $tsTree[$i+1][2];
                  last SWITCH;
              }
              if ($tsTree[$i] eq "context") {
                  @contextTree = @{$tsTree[$i+1]};
                  last SWITCH;
              }
            }
        }
        for (my $i = 0; $i < $#contextTree; ++$i) {
            if ($contextTree[$i] eq "message") {
                my @messageTree = @{$contextTree[$i+1]};
                my $messageId = $messageTree[0]{"id"};
                my $source = "";
                my $extracomment = "";
                for (my $j = 0; $j < $#messageTree; ++$j) {
                  SWITCH: {
                      if ($messageTree[$j] eq "source") {
                          $source = $messageTree[$j+1][2];
                          last SWITCH;
                      }
                      if ($messageTree[$j] eq "extracomment") {
                          $extracomment = $messageTree[$j+1][2];
                          last SWITCH;
                      }
                    }
                }
                if ($messageId eq $eeMessageId) {
                    $eeMessageIdIsInSpecCount += 1;
                    if ($OPT_VERBOSITY >= 1) {
                        printf STDOUT "++++++OK: id “%s” spec “%s” (%s)\n",
                        $eeMessageId, $extra_ui_spec_document,  myBasename($handoffFile);
                    }
                    ${$htmlOutRef} .= "<li>";
                    ${$htmlOutRef} .= sprintf "%s found in spec “%s” (%s)",
                    $eeMessageId, $extra_ui_spec_document,  myBasename($handoffFile);
                    ${$htmlOutRef} .= "</li>\n";
                }
            }
        }
    }
    if ($eeMessageIdIsInSpecCount == 0) {
        if ($OPT_VERBOSITY >= 1) {
            printf STDOUT "***ERROR: id “%s” not found in spec\n", $eeMessageId;
        }
        ${$htmlOutRef} .= "<li>";
        ${$htmlOutRef} .= sprintf "%s", $eeMessageId;
        ${$htmlOutRef} .= "</li>\n";
    }
    return $eeMessageIdIsInSpecCount;
}

#----------------------------------------------------------------------
# "main":

# Process command line options
my %opt;
unless (GetOptions(\%opt,
		   'verbosity=i',        \$OPT_VERBOSITY,
		   'version',            \$OPT_VERSION,
		   'help|h',             \$OPT_HELP,
		   'eedir=s',            \$OPT_EEDIR,
                   'handoffurl=s',       \$OPT_HANDOFF_URL,
                   'handoffdir=s',       \$OPT_HANDOFF_DIR,
                   'http-user=s',        \$OPT_HTTP_USER,
                   'http-passwd=s',      \$OPT_HTTP_PASSWD,
                   'skip-download',      \$OPT_SKIP_DOWNLOAD,
                   'output-dir=s',       \$OPT_OUTPUTDIR,
        )) {
    &usage ();
    exit 1;
}

if (!defined $OPT_VERBOSITY) {
    $OPT_VERBOSITY = 1;
}
if (!defined $OPT_VERSION) {
    $OPT_VERSION = 0;
}
if (!defined $OPT_HELP) {
    $OPT_HELP = 0;
}
if (!defined $OPT_EEDIR) {
    $OPT_EEDIR="/usr/share/l10n/meegotouch";
}
if (!defined $OPT_HANDOFF_URL) {
    $OPT_HANDOFF_URL="https://projects.maemo.org/svn/l10n/projects/harmattan/vendor/handoff/";
}
if (!defined $OPT_HANDOFF_DIR) {
    $OPT_HANDOFF_DIR="/tmp/handoff";
}
if (!defined $OPT_HTTP_USER) {
    $OPT_HTTP_USER="";
}
if (!defined $OPT_HTTP_PASSWD) {
    $OPT_HTTP_PASSWD="";
}
if (!defined $OPT_SKIP_DOWNLOAD) {
    $OPT_SKIP_DOWNLOAD = 0;
}
if (!defined $OPT_OUTPUTDIR) {
    $OPT_OUTPUTDIR = "$original_wd/messageid-check-results/";
}

if ($OPT_VERSION) {
    print "messageid-check $version\n";
    exit 0;
}

if ($OPT_HELP) {
    &usage ();
    exit 0;
}

if ($OPT_VERBOSITY >=1) {
    select (STDOUT);
    $OUTPUT_AUTOFLUSH = 1;
    select (STDERR);
    $OUTPUT_AUTOFLUSH = 1;
}

if (! -d $OPT_OUTPUTDIR) {
    mySystem("mkdir -p $OPT_OUTPUTDIR");
    if (! -d $OPT_OUTPUTDIR) {
        printf STDERR "Cannot create output directory %s\n", $OPT_OUTPUTDIR;
        myExit(1);
    }
}

if (!$OPT_SKIP_DOWNLOAD) {
    download();
}
else {
    @handoffFiles = glob ("$OPT_HANDOFF_DIR/*.ts");
}

readHandoffXmlTrees();

my $htmlOutToc = "";
my $htmlOutResultsDetail = "";
my $csvOut = "Invalid Message ID, Engineering English .qm file, Package, Package version, Package maintainer\n";

for my $engineeringEnglishFile (findEngineeringEnglishFiles()) {
    my $errorCount = 0;
    my $okCount = 0;
    my $missingEngineeringEnglishCount = 0;
    my $debianPackage = qx(dpkg -S $engineeringEnglishFile);
    $debianPackage =~ s/:.*$//;
    chomp($debianPackage);
    my $debianPackageMaintainerFull = "Unknown &lt;unknown\@unknown.com%gt;";
    my $debianPackageMaintainerMail = "unknown\@unknown.com";
    my $debianPackageVersion = "";
    my $debianPackageDescription = "";
    open (STATUS, "dpkg -s $debianPackage |") || die "Can’t open dpkg -s $debianPackage | : $!";
    binmode STATUS, ":utf8";
    while (<STATUS>) {
        if ($ARG =~ /Maintainer:\s+(.+)$/) {
            $debianPackageMaintainerFull = $1;
            $debianPackageMaintainerFull =~ /<(.+)>/;
            $debianPackageMaintainerMail = $1;
            $debianPackageMaintainerFull =~ s/</&lt;/;
            $debianPackageMaintainerFull =~ s/>/&gt;/;
        }
        if ($ARG =~ /Version:\s+(.+)$/) {
            $debianPackageVersion = $1;
        }
        if ($ARG =~ /Description:\s+(.+)$/) {
            $debianPackageDescription = $1;
        }
    }
    my $dpkgStatusDetails = qx(dpkg -s $debianPackage);
    if ($OPT_VERBOSITY >= 1) {
        printf STDOUT "------------------------------------------------------------\n";
        printf STDOUT "checking “%s” from package “%s”\n", $engineeringEnglishFile, $debianPackage;
    }

    my $htmlOutOkList = "";
    my $htmlOutErrorList = "";
    my $htmlOutMissingEeList = "";

    my $xmlParser = new XML::Parser(Style => 'Tree');
    open (EEFILE, "lconvert -o - -i $engineeringEnglishFile |") || die "Can’t open file lconvert $engineeringEnglishFile | : $!";
    my $tree = $xmlParser->parse(*EEFILE, ProtocolEncoding => 'UTF-8');
    close(EEFILE);
    if (! $tree->[1][4]) {
        if ($OPT_VERBOSITY >=1) {
            printf (STDOUT "%s has no context tree, probably empty, skipping ...\n",
                    $engineeringEnglishFile);
        }
        next;
    }
    my @contextTree = @{$tree->[1][4]};
    # print Dumper(@contextTree);
    for (my $i = 0; $i < $#contextTree; ++$i) {
        if ($contextTree[$i] eq "message") {
            my $source = $contextTree[$i+1][4][2];
            my $translation = $contextTree[$i+1][8][2];
            if (!$translation || $translation eq "!! " || $translation eq "") {
                ++$missingEngineeringEnglishCount;
                ++$totalNumberOfIdsLackingEngineeringEnglish;
                my $htmlOutMissingEeMessage = "";
                $htmlOutMissingEeMessage .= "<li>";
                $htmlOutMissingEeMessage .= sprintf "%s", $source;
                $htmlOutMissingEeMessage .= "</li>\n";
                $htmlOutMissingEeList .= $htmlOutMissingEeMessage;
            }
            my $htmlOutMessage = "";
            my $eeMessageIdIsInSpecCount =
                checkMessageIdFromSourceAgainstHandoff($engineeringEnglishFile, $source, \$htmlOutMessage);
            if ($eeMessageIdIsInSpecCount >= 1) {
                ++$okCount;
                $htmlOutOkList .= $htmlOutMessage;
            }
            else {
                ++$errorCount;
                ++$totalNumberOfIdsNotFoundInSpec;
                $htmlOutErrorList .= $htmlOutMessage;
                $csvOut .= "$source,$engineeringEnglishFile,$debianPackage,$debianPackageVersion,$debianPackageMaintainerMail\n";
            }
        }
    }
    $htmlOutResultsDetail .= <<"EOF";
        <div class="eefile">
        <div class="title">
        <a href="#$engineeringEnglishFile-ref" name="$engineeringEnglishFile">
        $engineeringEnglishFile
        </a>
        IDs in spec:
        <span class="okcolor">
        $okCount
        </span>
EOF

    $class = $errorCount?  "errorcolor" : "okcolor";
    $htmlOutResultsDetail .= <<"EOF";
        Invalid IDs:
        <span class="$class">
            $errorCount
        </span>
EOF

    $class = $missingEngineeringEnglishCount?  "errorcolor" : "okcolor";
    $htmlOutResultsDetail .= <<"EOF";
        IDs lacking EE:
        <span class="$class">
        $missingEngineeringEnglishCount
        </span>
        </div>
EOF

    $htmlOutResultsDetail .= <<"EOF";
        <div class="package">
        $debianPackage $debianPackageVersion
        </div>
        <div class="maintainer">
        <a href="mailto:$debianPackageMaintainerMail">$debianPackageMaintainerFull</a>
        </div>
EOF

    if ($errorCount > 0) {
        $htmlOutResultsDetail .= <<"EOF";
            <div class="errorlist">
            List of invalid IDs not found in the UI specs:
            <ul>
            $htmlOutErrorList
            </ul>
            </div>
EOF
    }

    if ($missingEngineeringEnglishCount > 0) {
        $htmlOutResultsDetail .= <<"EOF";
            <div class="errorlist">
            List of IDs where the engineering English is missing or empty:
            <ul>
            $htmlOutMissingEeList
            </ul>
            </div>
EOF
    }

    if ($okCount > 0) {
        $htmlOutResultsDetail .= <<"EOF";
            <div class="oklist">
            List of IDs found in the UI specs:
            <ul>
            $htmlOutOkList
            </ul>
            </div>
            </div>
EOF
    }

    # Table of Contents:
    $class = ($errorCount == 0 && $missingEngineeringEnglishCount == 0) ? "okbgcolor" : "errorbgcolor";
    my $engineeringEnglishFileBasename = myBasename($engineeringEnglishFile);
    $htmlOutToc .= <<"EOF";
        <tr>
        <td class="$class">
        $debianPackage
        </td>
        <td class="$class">
        $debianPackageVersion
        </td>
        <td class="$class">
        <a href="#$engineeringEnglishFile" name="$engineeringEnglishFile-ref">
        $engineeringEnglishFileBasename
        </a>:
        </td>
EOF

    $htmlOutToc .= <<"EOF";
        <td class="okbgcolor">
        $okCount
        </td>
EOF

    $class = $errorCount? "errorbgcolor" : "okbgcolor";
    $htmlOutToc .= <<"EOF";
        <td class="$class">
        $errorCount
        </td>
EOF

    $class = $missingEngineeringEnglishCount? "errorbgcolor" : "okbgcolor";
    $htmlOutToc .= <<"EOF";
        <td class="$class">
        $missingEngineeringEnglishCount
        </td>
        </tr>
EOF

}

$htmlOutToc .= <<"EOF";
    </table>
    </center>
EOF

my $htmlOutTocHeader = "";
$htmlOutTocHeader .= <<"EOF";
    <hr>
    <h2>Summary of results:</h2>
EOF

$class = $totalNumberOfIdsNotFoundInSpec? "errorcolor" : "okcolor";
$htmlOutTocHeader .= <<"EOF";
<span class="$class">
    <p>
    <b>
    Total number of Ids not found in the specification:
    $totalNumberOfIdsNotFoundInSpec
    </b>
    </p>
</span>
EOF

$class = $totalNumberOfIdsLackingEngineeringEnglish? "errorcolor" : "okcolor";
$htmlOutTocHeader .= <<"EOF";
<span class="$class">
    <p>
    <b>
    Total number of Ids where the engineering English is missing or empty:
    $totalNumberOfIdsLackingEngineeringEnglish
    </b>
    </p>  
</span>
EOF

$htmlOutTocHeader .= <<"EOF";
    <p>
    <a href="messageid-check-result.csv">
    CVS file with a list of all invalid message IDs.
    </a>
    </p>
    <center>
    <table class="summary">
    <caption style="caption-side:top">
    Overview of the number of IDs found or not found in the specifications.
    Click on the file name of the .qm file for details.
    </caption>
    <tr>
    <th>
    Debian package name
    </th>
    <th>
    version
    </th>
    <th>
    Engineering English .qm file
    </th>
    <th>
    IDs in spec
    </th>
    <th>
    Invalid IDs
    </th>
    <th>
    Missing EE
    </th>
    </tr>
EOF

my $htmlOutResultsDetailHeader = "";
$htmlOutResultsDetailHeader .= <<"EOF";
    <hr>
    <h2>Results in detail:</h2>
EOF

my $htmlOutIntroduction ="";
$htmlOutIntroduction .= <<"EOF";
    <hr>
    <h2>Introduction</h2>
    This page lists IDs which are used in
    the code but which are missing in the specifications. For all IDs used
    in the code, but not defined in the UI specifications, please do the
    following:
    <ol>
    <li>Check your code if those IDs are really in use</li>
    <li>Check if there is a typo in the ID</li>
    </ol>
    If there is no typo and the ID is
    really used, open a bug against the relevant UI Spec
    requesting a new ID:
    <ul>
    <li>component: Specifications</li>
    <li>CC: <a href=\"mailto:heidi.hendrell\@nokia.com\">Heidi Hendrell</a></li>
    </ul>
EOF

my $htmlOutBody =
    $htmlOutIntroduction
    . $htmlOutTocHeader
    . $htmlOutToc
    . $htmlOutResultsDetailHeader
    . $htmlOutResultsDetail;

writeHtml($htmlOutBody);

open (CSV, ">$OPT_OUTPUTDIR/messageid-check-result.csv") || die "can't open file $OPT_OUTPUTDIR/messageid-check-result.csv: $!";
binmode CSV, ":utf8";
printf CSV "%s", $csvOut;
close (CSV);

myExit (0);
