#!/usr/bin/perl -w

use warnings;
use strict;
use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );

# local classes
use czartool::Config;
use czartool::CzarDb;
use czartool::Gpc1Db;
use czartool::Pantasks;


my $czarDbName = "czardb";
my $save_temps = 1;
my $interval = undef;

GetOptions ( 
        "dbname|d=s" => \$czarDbName,
        "interval|i=s" => \$interval,
        );


my @states = ("full", "new", "drop", "wait");
my $config = new czartool::Config();
my $czarDb = $config->getCzarDbInstance();
my $gpc1Db = $config->getGpc1Instance();
my $pantasks = new czartool::Pantasks();

my @stdscienceLabels = undef;
my @distributionLabels = undef;
my @publishingLabels = undef;

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


###########################################################################
#
# Prints simple instructions
#
###########################################################################
sub printInstructions {

    print "| Usage: (s)ervers, (l)abels, (q)uit, or label number from table above: ";
}

###########################################################################
#
# Polls waiting for input from user 
#
###########################################################################
sub promptPoll {

    @stdscienceLabels = @{$pantasks->getLabels("stdscience")};
    @distributionLabels = @{$pantasks->getLabels("distribution")};
    @publishingLabels = @{$pantasks->getLabels("publishing")};
    checkAllLabels("new");
    printInstructions();

    my $key;
    system "stty cbreak < /dev/tty > /dev/tty 2>&1";
    while (($key=getc) ) {
        last if $key eq "q";

        if ($key eq "s") {checkServers();}
        elsif ($key eq "l") {checkAllLabels("new");}
        elsif ($key eq "u") {$pantasks->getServerCurrentStatus("stdscience");}
        elsif ($key =~ m/[0-9]/) {my $key2=getc; checkOneLabel($stdscienceLabels[($key.$key2)-1]);}
        printInstructions();

    };
    system "stty -cbreak < /dev/tty > /dev/tty 2>&1";
}

###########################################################################
#
# Compares two arrays and stores the differences
#
###########################################################################
sub getArrayDifferences {

    my @array1 = @{$_[0]};
    my @array2 = @{$_[1]};

    my @isect;
    my @diff;
    my %count;

    my $item;
    foreach $item (@array1, @array2) {$count{$item}++;}

    foreach $item (keys %count) {
        if ($count{$item} == 2) {
            push @isect, $item;
        } else {
            push @diff, $item;
        }
    }

    return \@diff;
}

###########################################################################
#
# Checks all servers to see if they are alive and running
#
###########################################################################
sub checkServers {

    my @servers = ("addstar", "cleanup", "detrend", "distribution", "pstamp", "update", "publishing", "registration", "replication", "stdscience", "summitcopy");
    printf("\n+-----------------------------------------------+\n");
    printf("|                      Servers                  |\n");
    printf("+--------------+---------+----------------------+\n");
    printf("|    server    |  alive? |  Scheduler running?  |\n");
    printf("+--------------+---------+----------------------+\n");
    my $server;
    foreach $server (@servers) {

        my @results = `czartool_checkServer.pl -s $server`;

        printf("| %12s ", $server);
        chomp($results[0]);
        chomp($results[1]); 
        printf("|   %3s   |         %3s          |\n", $results[0], $results[1]);
    }

    printf("+--------------+---------+----------------------+\n");
}

###########################################################################
#
# Takes label name or number
#
###########################################################################
sub labelDetails {

    print "\nPlease enter the label name, or number from table above: ";
    my $input = <STDIN>;
    chomp($input);
    if ($input =~ m/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$/) {
        return checkOneLabel($stdscienceLabels[$input]);
    }

    checkOneLabel($input);
}

###########################################################################
#
# Checks one label and prints results in a table
#
###########################################################################
sub checkOneLabel {
    my ($label) = @_;

    chomp($label);
    my $stage;

    printf("\n|  %32s  \n", $label);
    printf("+------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");
    printf("|   state    |");
    foreach $stage (@stages) {

        printf("%14s|", $stage)
    }
    printf("\n");
    printf("+------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");

    my $state;
    my $i=0;
    foreach $state (@states) {

        chomp($label);
        printf("| %10s ", $state);

        foreach $stage (@stages) {

            printf("|%14s", getStateAndFaultsString($label, $state, $stage));
        }

        printf("|\n");
        $i++;
    }

    printf("+------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");

}

###########################################################################
#
# Checks all labels for a particular state and prints results in a table
#
###########################################################################
sub checkAllLabels {
    my ($state) = @_;
#print time, $/;
    my $stage;

    printf("|\n");
    printf("+-----+----------------------------------+---------------+---------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");
    printf("| no  |              label               | distributing? |  publishing?  |");

    my $stdsLabel;
    my $distLabel;
    my $pubLabel;
    my $distributing;
    my $publishing;
    my $i=1;
    foreach $stage (@stages) {

        printf("%14s|", $stage)
    }
    printf("\n");
    printf("+-----+----------------------------------+---------------+---------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");

    foreach $stdsLabel (@stdscienceLabels) {

        $distributing = 0;
        chomp($stdsLabel);
        foreach $distLabel (@distributionLabels) {
            chomp($distLabel);
            if ($stdsLabel eq $distLabel) { $distributing = 1; last;}
        }

        foreach $pubLabel (@publishingLabels) {
            chomp($pubLabel);
            if ($stdsLabel eq $pubLabel) { $publishing = 1; last;}
        }

        printf("| %3d ", $i);
        printf("| %32s ", $stdsLabel);
        printf("| %10s    ", $distributing ? "yes" : "NO" );
        printf("| %10s    ", $publishing ? "yes" : "NO" );

        foreach $stage (@stages) {

            printf("|%14s", getStateAndFaultsString($stdsLabel, $state, $stage));
        }

        printf("|\n");
        $i++;
    }

    printf("+-----+----------------------------------+---------------+---------------+");
    foreach $stage (@stages) {
        print "--------------+"
    }
    printf("\n");

}

###########################################################################
#
# Returns state and fault-count (if new) as a string TODO untidy
#
###########################################################################
sub getStateAndFaultsString {
    my ($label, $state, $stage) = @_;

    my $new = $gpc1Db->countExposures($label, $stage, $state);

    #if ($state ne "new") {return $new;}

    my $faults = $gpc1Db->countFaults($label, $stage, $state);

    if ($faults < 1) {return $new;}

    return $new."(".$faults.")";
}


