#!/usr/bin/perl

BEGIN {
  use FindBin;
  do $FindBin::RealBin . '/../etc/config.pm' ;
}

use strict;
use warnings;
use Time::HiRes qw/time sleep/;
use JSON;

use constant OP_HELP     => 'help';
use constant OP_STATUS   => 'status';
use constant OP_WAIT_UP  => 'waitup';

use constant TIMEOUT     => 60;
use constant WAIT_PERIOD => 1;

sub main;
sub opHelp;
sub opStatus;
sub opWaitUp;

my %handlers = (
  &OP_HELP    => \&opHelp,
  &OP_STATUS  => \&opStatus,
  &OP_WAIT_UP => \&opWaitUp,
);

main;

sub main {
  my $op;

  @ARGV and $op = $ARGV[0];

  $op or do {
    print "*** ERROR: requires a command\n\n";
    opHelp;
    exit 1;
  };

  $handlers{$op} or do {
    printf "*** ERROR: requires a known command, not '%s'\n\n", $op;
    opHelp;
    exit 1;
  };

  # return to bash 0 when ok, else 1
  &{$handlers{$op}}(@ARGV) and exit 0;
  exit 1;
}

sub opHelp {
  print 'Help:
  help           this help
  status         get status as a json
  waitup         wait until cypher daemon is running
    -t <seconds> max time before returning an error (' . TIMEOUT . ')
    -w <seconds> time between two tries (' . WAIT_PERIOD . ')
';

  return 1;
}

sub getStatus {
  my $obj;

  eval {
    $/ = undef;
    open FILE, '<' . MOUNT_DIR . STATUS_FILE or die;
    my $json = <FILE>;
    close FILE;
    $obj = decode_json $json;
  };
  
  return $obj;
}

# returns 0 when not detected as functional
# returns 1 when detected as functional
sub opStatus {
  my $status = getStatus;
  $status or return 0;

  my $json = JSON->new->pretty(1);
  eval {
    print $json->encode($status);
  };
  $@ and return 0;

  return 1;
}

# returns 0 when not detected as functional
# returns 1 when detected as functional
sub opWaitUp {
  my ($op, @args) = @_;
  my $timeout = TIMEOUT;
  my $wait = WAIT_PERIOD;

  while (@args) {
    for (shift @args) {
      /^-t$/ and do {
        @args or die "$op $_ requires an integer\n";
        $timeout = shift @args;
        next;
      };
      /^-w$/ and do {
        @args or die "$op $_ requires an integer\n";
        $wait = shift @args;
        next;
      };
      die "Unkown argument '$_'\n";
    }
  }

  my $status;
  my $running = 1;
  $SIG{ALRM} = sub { $running = 0; };
  alarm $timeout;
  while ($running) {
    my $status = getStatus;
    $status and $status->{running} and do {
      print "Service is running\n";
      return 1;
    };
    sleep $wait;
  }
  alarm 0;
  $SIG{ALRM} = undef;
  print "Timeout occurred\n";

  return 0;
}

