#!/usr/bin/perl -w

use strict;
use Carp;

use IO::Socket;
use Getopt::Long;

use constant RECORDER_SERVER => 50080;

sub send_data($);
sub send_cmd($);
sub addline;

my @recordernames;
if (defined $ENV{RECORDERMON}) {
  @recordernames = split /\s+/, $ENV{RECORDERMON};
} else {
  #@recordernames = ('pkvsi1', 'pkvsi2');
  @recordernames = ('pkvsi1-ext', 'cavsi1', 'mpvsi2-ext', 'hovsi.phys.utas.edu.au');
  #@recordernames = ('pkvsi1-ext', 'pkvsi2-ext', 'cavsi1', 'cavsi2', 'mpvsi1-ext', 'mpvsi2-ext');
}
	     
GetOptions('recorder=s'=>\@recordernames);

my $recordername;
my @lines = ();
while (1) {
  @lines = ();

  my $first = 1;
  foreach my $rec (@recordernames) {
    $recordername = $rec;
    my ($shortname) = $recordername =~ /(^[^.]*)/;

    if ($first) {
      $first = 0;
    } else {
      addline(sprintf("%s\n", '-'x40));
    }

    my $settings =  send_cmd('status-settings');
    if (!defined $settings) {
      addline "Failed to connect to $shortname\n";
      next;
    }
    
    my ($bandwidth) = $settings=~ /Bandwidth:\s*(\S+)/;
    my ($vsibmode) = $settings=~ /VSIB Mode:\s*(\d+)/;
    my ($rate) = $settings=~ /Clock rate:\s*(\d+) MHz/;
    my ($compression) = $settings=~ /Compression:\s*(\S+)/;

    my $server = send_cmd('status-server');
    if (!defined $server) {
      addline "Failed to connect to $shortname\n";
      next;
    }

    my ($time) = $server =~ /Current Time:\s*(\S.*\S)/;
    my ($status) = $server =~ /Recording Status:\s*(\S.*\S)/;
    my $recording = 0;
    $recording = 1 if ($status eq 'Recording.');

    my @sampstats = ();
    my $record = send_cmd('status-record');
    if (! defined $record) {
      addline "Failed to connect to $shortname\n";
      next;
    }

    my ($filetime, $block) = $record =~ /last file opened at day (\d+, \S+), block (\d+)/;
    my ($bigbuf, $bigbufpercent) = $record=~ /BIGBUF free memory = (\d+) MB \((\S+)\)/;
    $bigbufpercent = ' ' if (!defined $bigbufpercent);
    my $ppsok = 0;
    if ($record =~ /PPS signal OK/) {
      $ppsok = 1;
    }
    my ($ppsmissed, $nppschecked) = $record=~ /PPS missed (\d+) times from last (\d+) files/;
  
    my $nchan = ($compression =~ tr/x//);
    my $bits = 8 * $nchan/4;

    if ($vsibmode==2) {
      $bits *= 8;
      $nchan *=2;
    }
    $nchan /=4 if ($bandwidth == 64);
    $nchan /=2 if ($bandwidth == 32);

    my $bitrate = $nchan*$bandwidth*2*2; # Times compression factor!
    
    while ($record =~ /Chan (\d+):  (\d.*\d)/g) {
      $sampstats[$1] = $2;
    }
    my @compressedstats;
    for (my $i=0; $i<scalar(@sampstats); $i++) {
      push @compressedstats, sprintf("CH%d: $sampstats[$i]", $i)
	if defined $sampstats[$i];
    }
    @sampstats = @compressedstats;

    addline(sprintf "%-10s %-29s", $shortname, $time);
    if (defined($sampstats[0]) && $recording) {
      addline(sprintf($sampstats[0]));
    }
    addline(sprintf("\n"));

    addline(sprintf("%-40s", $status));
    if (defined($sampstats[1]) && $recording) {
      addline sprintf $sampstats[1];
    }
    addline sprintf("\n");

    next if (! $recording);

    addline(sprintf("%2s MHz %dch, %3d Mbps  bigbuf %4s       ", 
		    $bandwidth, $nchan, $bitrate, $bigbufpercent));
    if (defined($sampstats[2])) {
      addline sprintf($sampstats[2]);
    }
    addline sprintf("\n");
    
    if ($ppsok) {
      addline sprintf("PPS: OK       ");
    } else {
      addline sprintf("PPS: MISSING  ");
    }
    $ppsmissed = 0 if (!defined $ppsmissed);
    $nppschecked = 0 if (!defined $nppschecked);
    addline(sprintf "  missed %3d/%-3d          ", $ppsmissed, $nppschecked);
    if (defined($sampstats[3])) {
      addline sprintf($sampstats[3]);
    }
    addline sprintf("\n");

    $filetime = ' ' if (!defined $filetime);
    $block = 0 if (!defined $block);
    addline(sprintf("File: block %8d at %s    ", $block, $filetime));
    if (defined($sampstats[4])) {
      addline sprintf($sampstats[4]);
    }
    addline sprintf("\n");

    foreach my $ss (@sampstats[5..$#sampstats]) {
      addline sprintf("%s%s\n", ' 'x40, $ss);
    }
  }
  system "clear";
  foreach (@lines) {
    print;
  }
  sleep(5);
}

sub server_comm {
  my ($type, $message) = @_;

  # Connect to the recorder server
  my $socket = IO::Socket::INET->new(PeerAddr => $recordername,
				     PeerPort => RECORDER_SERVER
				     );
  return undef if (!defined $socket);

  print $socket "<$type>$message</$type>";

  # Get response
  
  my $ret = "";
  while(<$socket>){
    $ret .= $_;
  }
  close($socket);

  if ($ret =~ /<fail>(.*)<\/fail>/s) {
    carp "$1";
    return undef;
  } elsif ($ret =~ /<succ \/>/s) {
    return "";
  } elsif ($ret =~ /<status>(.*)<\/status>/s) {
    return $1;
  } else {
    warn "Did not understand server reponse ($ret): $!\n";
    return undef;
  }
}

sub send_data($) {
  return server_comm('data', shift);
}

sub send_cmd($) {
  return server_comm('cmnd', shift);
}

sub addline {
  foreach (@_) {
    push @lines, $_;
  }
}
