#!/usr/bin/perl -w

use warnings;
use strict;

use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
use POSIX qw/strftime/;
use CGI::Pretty qw[:standard];

use czartool::CzarDb;
use czartool::Gpc1Db;
use czartool::Plotter;
use czartool::StageMetrics;
use czartool::Metrics;


package czartool::DayMetrics;
our @ISA = qw(czartool::Metrics);    # inherits from Metrics class

###########################################################################
#
# Constructor (overrides superclass)
#
###########################################################################
sub new {
    my ($class) = @_;

    # Call the constructor of the parent class
    my $self = $class->SUPER::new(
            $_[1],  # config object 
            $_[2],  # verbose
            $_[3]   # save_temps
            ); 

    $self->{day} = $_[4];

    my $yesterday =  $self->{czarDb}->subtractInterval($self->{day}, "1 DAY");

    # sort out times
    $self->{begin} =  "$yesterday " . $self->{config}->getMetricsStartTime();
    $self->{end} = $self->{czarDb}->addInterval($self->{begin}, "1 DAY");
    $self->{chipEnd} = $self->{czarDb}->addInterval($self->{begin}, "12 HOUR");

    # create path, dir and html file
    $self->{path} = "$self->{baseDir}/$self->{day}";
    rmdir($self->{path});
    mkdir($self->{path}, 0777);
    $self->{plotter}->setOutputPath($self->{path});

    if ($self->{verbose}) {print "* Creating metrics for $self->{day}\n";}

    bless $self, $class;

    return $self;
}

###########################################################################
#
# Writes HTML document
#
###########################################################################
sub writeHTML {
    my ($self) = @_;

    # create HTML file and write header stuff
    $self->createHtml("IPP Metrics for $self->{day}");
    my $htmlFile = $self->{htmlFile};

    # summit and chip exposures
    my $summitExposures = $self->{gpc1Db}->countScienceExposuresFromLastNight($self->{day});
    my $chipMetrics = new czartool::StageMetrics("chip", "all_stdscience_labels", $self->{begin}, $self->{chipEnd});
    $self->{czarDb}->runAnalysis($chipMetrics);

    my $previousDay = $self->{czarDb}->subtractInterval($self->{day}, "1 DAY");
    my $nextDay = $self->{czarDb}->addInterval($self->{day}, "1 DAY");

    print $htmlFile "<h5  align=\"middle\">";
    print $htmlFile "<a href=\"../$previousDay/index.html\"> \< previous day</a> | <a href=\"../index.html\">all</a> | <a href=\"../$nextDay/index.html\">next day \></a><br>\n";
    print $htmlFile "Measured from $self->{begin} to $self->{end} HST<br>\n";
    printf ( $htmlFile "%d exposures taken on summit last night, %d through chip today</h5>\n", 
            $summitExposures, $chipMetrics->getProcessed() ? $chipMetrics->getProcessed() : 0 );
    print $htmlFile "</head>\n";
    print $htmlFile "<body>\n";



    my $labels = undef;
    my $label;
    if (!$self->{czarDb}->getStdscienceLabelsInTimePeriod($self->{begin}, $self->{end}, \$labels)) {next;}

    my $size = @{$labels};
    my $table;
    my $haveLabelData;
    my %initialPendingTotals;
    my %processedTotals;
    my %finalPendingTotals;
    my %faultTotals;
    my %labelTables;

    my @stages = (
            "chip", 
            "cam", 
            "fake", 
            "warp", 
            "stack", 
            "staticsky", 
            "diff", 
            "dist",
            "chipbackground");


# loop through all labels and create tables for each that have content
    foreach my $row ( @{$labels} ) {
        my ($label) = @{$row};


        $table = "<table border='1'>";
        $table .= "  <tr>\n";
        $table .= "    <th>Stage</th>\n";
        $table .= "    <th>Initial Pending</th>\n";
        $table .= "    <th>Started</th>\n";
        $table .= "    <th>25% complete</th>\n";
        $table .= "    <th>50% complete</th>\n";
        $table .= "    <th>75% complete</th>\n";
        $table .= "    <th>90% complete</th>\n";
        $table .= "    <th>95% complete</th>\n";
        $table .= "    <th>Finished</th>\n";
        $table .= "    <th>Time taken</th>\n";
        $table .= "    <th>Processed</th>\n";
        $table .= "    <th>Exp per hour</th>\n";
        $table .= "    <th>Final Pending</th>\n";
        $table .= "  </tr>\n";

        $haveLabelData = 0;
        foreach my $stage ( @stages ){

            my $stageMetrics = new czartool::StageMetrics($stage, $label, $self->{begin}, ($stage eq "chip") ? $self->{chipEnd} : $self->{end});
            if (!$self->{czarDb}->runAnalysis($stageMetrics)) {next;}

            if (!$stageMetrics->anythingProcessed()) {next;}

            if ($stageMetrics->getProcessed() > 0) {$haveLabelData = 1;};

            $table .= "  <tr>\n";
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getStage() );
            $table .= sprintf( "    <td>%d</td>\n", $stageMetrics->getInitialPending() ? $stageMetrics->getInitialPending() : "0" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getStarted() ? $stageMetrics->getStarted() : "");
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished25() ? $stageMetrics->getFinished25() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished50() ? $stageMetrics->getFinished50() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished75() ? $stageMetrics->getFinished75() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished90() ? $stageMetrics->getFinished90() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished95() ? $stageMetrics->getFinished95() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getFinished100() ? $stageMetrics->getFinished100() : "-" );
            $table .= sprintf( "    <td>%s</td>\n", $stageMetrics->getTotalTime() ? $stageMetrics->getTotalTime() : "-" );
            $table .= sprintf( "    <td>%d</td>\n", $stageMetrics->getProcessed() ? $stageMetrics->getProcessed() : "0" );
            $table .= sprintf( "    <td>%.2f</td>\n", $stageMetrics->getRate() ? $stageMetrics->getRate() : "0" );
            $table .= sprintf( "    <td>");
            if ($stageMetrics->getFinalPending() > 0) {$table .= "<font color=\"red\">";}
            $table .= sprintf( "%d\n", $stageMetrics->getFinalPending() );
            if ($stageMetrics->getFinalPending() > 0) {$table .= "</font>\n";}
            $table .= sprintf( "</td>");
            $table .= "  </tr>\n";

            if (!$initialPendingTotals{$stage}) {$initialPendingTotals{$stage} = 0;}
            $initialPendingTotals{$stage} = $initialPendingTotals{$stage} + $stageMetrics->getInitialPending();
            if (!$processedTotals{$stage}) {$processedTotals{$stage} = 0;}
            $processedTotals{$stage} = $processedTotals{$stage} + $stageMetrics->getProcessed();
            if (!$finalPendingTotals{$stage}) {$finalPendingTotals{$stage} = 0;}
            $finalPendingTotals{$stage} = $finalPendingTotals{$stage} + $stageMetrics->getFinalPending();
            if (!$faultTotals{$stage}) {$faultTotals{$stage} = 0;}
            $faultTotals{$stage} = $faultTotals{$stage} + $stageMetrics->getFaults();
        }

        $table .= "</table>";
        $table .= "<br>\n";

        if ($haveLabelData) { 
            $labelTables{$label} = $table; 
            if ($self->{verbose}) {print " - $label\n";}
        }
    }

    # create contents
    print $htmlFile "<h2>Contents</h2>\n";
    print $htmlFile "<a href=\"#surveys\">Survey timings</a><br>\n";
    print $htmlFile "<a href=\"#summaryplot\">Summary plots</a><br>\n";
    print $htmlFile "<a href=\"#stages\">Stage totals</a><br>\n";
    print $htmlFile "<a href=\"#mask\">Magic mask fraction</a><br>\n";
    foreach my $label (keys (%labelTables)) {

        print $htmlFile "<a href=\"#$label\">$label</a><br>\n";
    }

    # survey table
    if ($self->{verbose}) {print " * creating survey table\n";}
    $self->printSurveyTable();

    # some summary plots
    if ($self->{verbose}) {print " * creating summary plots\n";}
    $self->createSummaryPlots();

    # magic mask plots
    if ($self->{verbose}) {print " * creating mask plots\n";}
    $self->createMaskPlots($self->{day}, $self->{day});

    # table for stage totals
    $table = "<a name=\"stages\"></a>\n";
    $table .= "<h2  align=\"middle\">Stage totals <a href=\"#top\">(top)</a></h1>\n";
    $table .= "<table border='1'>";
    $table .= "  <tr>\n";
    $table .= "    <th>Stage</th>\n";
    $table .= "    <th>Initial Pending</th>\n";
    $table .= "    <th>Processed</th>\n";
    $table .= "    <th>Final Pending</th>\n";
    $table .= "    <th>Remaining Faults</th>\n";
    $table .= "  </tr>\n";
    foreach my $stage ( @stages ){

        $table .= "  <tr>\n";
        $table .= sprintf( "    <td>%s</td>\n", $stage );
        $table .= sprintf( "    <td>%d</td>\n", $initialPendingTotals{$stage} ? $initialPendingTotals{$stage} : 0);
        $table .= sprintf( "    <td>%d</td>\n", $processedTotals{$stage} ? $processedTotals{$stage} : 0);
        $table .= sprintf( "    <td>%d</td>\n", $finalPendingTotals{$stage} ? $finalPendingTotals{$stage} : 0);
        $table .= sprintf( "    <td>%d</td>\n", $faultTotals{$stage} ? $faultTotals{$stage} : 0);
        $table .= "  </tr>\n";
    }
    $table .= "</table>";
    $table .= "<br>\n";

    print $htmlFile $table;

    # print all label tables to page
    foreach my $label (keys (%labelTables)) {

        print $htmlFile "<a name=\"$label\"></a>\n";
        print $htmlFile "<h2  align=\"middle\">$label <a href=\"#top\">(top)</a></h1>\n";
        $self->{plotter}->createTimeSeries($label, undef, $self->{begin}, $self->{end}, 1, 1, 1);
        print $htmlFile "<img src=\"czarplot_linear_".$label."_all_stages_t.png\" alt=\"All stages for $label for $self->{day}\" />\n";
        $self->{plotter}->createHistogram($label, $self->{begin}, $self->{end}, 0, 0, 0);
        print $htmlFile "<img src=\"czarplot_linear_".$label."_all_stages_h.png\" alt=\"All stages for $label for $self->{day}\" />\n";

        print $htmlFile $labelTables{$label};
    }


    $self->finishHtml();
}

###########################################################################
#
# Creates a survey table
#
###########################################################################
sub printSurveyTable() {
    my ($self) = @_;

    my $htmlFile = $self->{htmlFile};

    print $htmlFile "<a name=\"surveys\"></a>\n";
    print $htmlFile "<h2  align=\"middle\">Survey timings <a href=\"#top\">(top)</a></h1>\n";
    print $htmlFile "<table border='1'>";
    print $htmlFile "  <tr>\n";
    print $htmlFile "    <th>Survey</th>\n";
    print $htmlFile "    <th>Started chip</th>\n";
    print $htmlFile "    <th>Finished distribution</th>\n";
    print $htmlFile "    <th>Time taken</th>\n";
    print $htmlFile "  </tr>\n";

    # OSS survey
    my ($started, $finished, $timeTaken) = undef;
    $self->{czarDb}->getDayTimings("OSS.nightlyscience", "chip", "diff", $self->{begin}, \$started, \$finished, \$timeTaken);
    $self->printSurveyDetails("OSS", $started, $finished, $timeTaken);

    # MDF surveys
    my @mdfs = ("M31.nightlyscience",
            "MD01.nightlyscience", 
            "MD02.nightlyscience", 
            "MD03.nightlyscience", 
            "MD04.nightlyscience", 
            "MD05.nightlyscience", 
            "MD06.nightlyscience", 
            "MD07.nightlyscience", 
            "MD08.nightlyscience", 
            "MD09.nightlyscience", 
            "MD10.nightlyscience",
            "MD11.nightlyscience");

    my $earliest = "2099-01-01 00:00:00";
    my $latest = "2001-01-01 00:00:00";

    my $mdf;
    my $haveStart = 0;
    my $haveEnd = 0;
    foreach $mdf (@mdfs) {

        if ($self->{czarDb}->getDayTimings($mdf, "chip", "dist", $self->{begin}, \$started, \$finished, \$timeTaken)) {

            if ($started && $self->{czarDb}->isBefore($started, $earliest)) {$earliest = $started; $haveStart = 1;}
            if ($finished && $self->{czarDb}->isBefore($latest, $finished)) {$latest = $finished; $haveEnd = 1;}
        }
    }

    if (!$haveStart) {$earliest = undef;}
    if (!$haveEnd) {$latest = undef;}
    if (!$haveStart || !$haveEnd) {$timeTaken = undef;}

    else {$timeTaken = $self->{czarDb}->diffTimes($latest, $earliest);}
    $self->printSurveyDetails("MDF", $earliest, $latest, $timeTaken);

    $self->{czarDb}->getDayTimings("all_stdscience_labels", "chip", "dist", $self->{begin}, \$started, \$finished, \$timeTaken);
    $self->printSurveyDetails("All", $started, $finished, $timeTaken);

    print $htmlFile "</table>\n";
}

###########################################################################
#
# Creates a row in the survey table
#
###########################################################################
sub printSurveyDetails() {
    my ($self, $survey, $started, $finished, $timeTaken, $processed, $pending) = @_;

    my $htmlFile = $self->{htmlFile};

    print $htmlFile "  <tr>\n";
    print $htmlFile "    <td>$survey</td>\n";
    printf ($htmlFile "    <td>%s</td>\n", $started ? $started : "no");
    printf ($htmlFile "    <td>%s</td>\n", $finished ? $finished : "no");
    printf ($htmlFile "    <td>%s</td>\n", $timeTaken ? $timeTaken : "na");
    print $htmlFile "  </tr>\n";
}
1;
