#!/usr/bin/perl -w
use strict;

use IO::Socket::INET;
use File::Basename;
use Filesys::Df;
use Astro::Time;
use POSIX;

use PX14Mon;

$Astro::Time::StrZero=2;

my @disks = ('/mnt/raid_0', '/mnt/raid_1', '/mnt/raid_2');

my $pxmon = new PX14Mon();

my $sock = new IO::Socket::INET(
    LocalPort => 50080,
    Listen =>5,
    Reuse =>1) || die "Cannot create socket: $!\n";

print "Waiting for connection\n";

my $buf = "";
my $newbuf;
my $data;

my $t0 = time();

my $lastbuf = -1;

my $recording = 0;
my $maybestalled = 0;
while (1) {

  my $client = $sock->accept();

  printf("Connection from %s:%d\n", $client->peerhost(), $client->peerport());

  my ($mark5b, $invert);
  while (1) {
    $client->recv($newbuf, 1024);

    $buf.=$newbuf;

    if ($buf =~ /(.*?)<cmnd>(.*?)<\/cmnd>(.*)/) {
      print "Command $2\n";
      if ($1) {
	warn "Skipped: $1!!\n";
      }

      if ($2 eq 'status-recsettings') {

	my $thisbuf = $pxmon->bufdone;
	if ($pxmon->recording()) {

	  if ($thisbuf==$lastbuf) {
	    if ($maybestalled) {
	      $recording = 0;
	      warn "Recorder has stalled - marking as not recording ($thisbuf)\n";
	    } else {
	      $maybestalled = 1;
	      warn "Recorder may be stalled - will wait for next message to be sure\n";
	    }
	  } else {
	    $maybestalled = 0;
	    $recording = 1;
	  }
	} else {
	  $recording = 0;
	}
	$lastbuf = $thisbuf;

	if ($recording) {
	  my $recdir = $pxmon->recpath;
	  my $outdir = basename($recdir);
	  my $outdisk = dirname($recdir);
	  my $label = basename($outdisk);
	  my $bandwidth = $pxmon->bandwidth;
	  my $clockrate = $bandwidth*2;
	  my $rectime = $pxmon->recordtime();
	  my $exper = $pxmon->exper;
	  if ($rectime<200) {
	    $rectime = sprintf("%.1fs", $rectime);
	  } elsif ($rectime<3600) {
	    $rectime = sprintf("%.1fm", $rectime/60);
	  } else {
	    $rectime = sprintf("%.1fh", $rectime/3600);
	  }
	  my $filesize = $pxmon->filesize();
	  my $bufsize = $pxmon->bufsize;
	  if ($pxmon->mark5b) {
	    $mark5b = 'enabled';
	  } else {
	    $mark5b = 'disabled'
	  }
	  if ($pxmon->invert) {
	    $invert = 'enabled';
	  } else {
	    $invert = 'disabled'
	  }
	  my ($mode);
	  if ($pxmon->nchan==2) {
	    $mode = 2;
	  } else {
	     $mode = 3;
	  }
	  
	  $data = <<"END";
<status>Recording Settings:
 Record time:      ${rectime}
 Start date:       not set
 Start time:       not set
 Output directory: $outdir
 Filename prefix:  $exper
 Compression:      xxxx
 VSIB Mode:        $mode
 Bandwidth:        $bandwidth
 VSIB device:      px14400
 File size:        $filesize secs
 Block size:       $bufsize B
 Clock rate:       $clockrate MHz
 Mark5B recording: $mark5b
 Invert recording: $invert
 Target recorder:  local
 Output disk:      $outdisk
 Disk label:       $label
 Auto execute:     disabled
 Auto round start: disabled
 Auto disk select: none
 Selectable disks: none</status>
END
	} else {
	  $data = <<"END";
<status>Not currently recording.</status>
END
	}

      } elsif ($2 eq 'status-server') {
	my $servertime = strftime "%T %d/%m/%Y", gmtime;
	my $uptime = turn2str((time() - $t0)/(60*60*24),'H',0);
	my $bandwidth = int $pxmon->bandwidth;
	my $nchan = $pxmon->nchan;
	my $rate = $bandwidth*2*$nchan*$pxmon->bits;
	my $compression;
	if ($nchan == 1) {
	    $compression = 'xo';
	} else {
	    $compression = 'xxxx';
	}
	my $recstate;
	if ($recording) {
	  $recstate = 'Recording';
	} else {
	  $recstate = 'Not recording';
	}
	my $prefix = $pxmon->exper;
	my $remaining = $pxmon->recordtime - ($pxmon->filetime - $pxmon->starttime);
	$remaining = turn2str($remaining/60/60/24, 'H', 0);
	my @df;
	my $i=1;
	foreach (@disks) {
	  my $disk_df = df($_);
	  my $label = basename($_);
	  my $total = int $disk_df->{blocks}/1024;
	  my $free = int $disk_df->{bfree}/1024;
	  my $percent = int($free/$total*100);
	  my $timeleft = turn2str($free*8/$rate/60.0/60/24, 'H',0);
	  
	  push @df, "  disk $i [$_ \"$label\"]: TOTAL: $total MB FREE: $free MB ($percent%) TIME: $timeleft";
	  $i++;
	}
	$data = <<"END";
<status>Current Time: $servertime
Server uptime: $uptime
Current Experiment: $prefix (manual)
Time until end: $remaining
Next Experiment: N/A
Time until start: N/A
Current settings: CH=$compression BW=$bandwidth FT=N BR=$rate
Recording Status: ${recstate}.
Receiving Status: Not receiving.
END

	$data .= "Disk Space:";
	foreach (@df) {
	  $data .= "\n$_";
	}
	$data .= "</status>";

      } elsif ($2 eq 'status-record') {

	my $recpath = $pxmon->recpath;
	my $path = basename($recpath);
	my $disk = dirname($recpath);
	my $label = basename($disk);
	my $disk_df = df($disk);
	my $free = int $disk_df->{bfree}/1024;
	my $rate = $pxmon->bandwidth*2*$pxmon->nchan*$pxmon->bits;
	my $timeleft = turn2str($free*8/$rate/60.0/60/24, 'H',0);
	my $file = $pxmon->currentfile;
	my $block = $pxmon->bufdone;
	my $filetime = strftime "%j, %T", localtime($pxmon->filetime);
	my $remaining = $pxmon->recordtime - ($pxmon->filetime - $pxmon->starttime);
	$remaining = turn2str($remaining/60/60/24, 'H', 0);
	my $prefix;
	my $recstate;
	if ($recording) {
	  $recstate = 'Recorder process running';
	  $prefix = <<"END";
/home/vlbi/bin/px14_record
Recording will finish in $remaining.
Remaining recording time on local:$disk: $timeleft
END
	} else {
	  $recstate = 'Recorder process not running';
	  $prefix = 'Last recording:'
	}

	$data = <<"END";
<status>$recstate;.
$prefix
last file opened at day $filetime, block $block ($file)
recording to disk local:$disk ($label), path $path
BIGBUF free memory = 512 MB (100%)
PPS signal OK
PPS missed 0 times from last 100 files
Time between files: avg =   60.00 s, max = 60 s
Chan 0:  17.30  32.70  32.70  17.30
Chan 1:  17.30  32.70  32.70  17.30
</status>
END

      } else {

	print "Unknown command!!!!\n";

	$data = '<fail>error 17: the command issued is not valid</fail>';

      }

      $data .= "\0";
      $client->send($data);
      $client->close();
      $buf = '';
      last;
    }
  }
}
