#!/usr/bin/perl

use strict;
use warnings;
use Log::Log4perl qw(:easy);
use Getopt::Long qw(GetOptions);

my $log_file = "gsgd.log";
sub get_log_name { return $log_file; };
my $log_conf = q(
log4perl.rootLogger = INFO, LOG1, screen
log4perl.appender.LOG1 = Log::Log4perl::Appender::File
log4perl.appender.LOG1.filename = sub { get_log_name(); }
log4perl.appender.LOG1.mode = append
log4perl.appender.LOG1.layout = Log::Log4perl::Layout::PatternLayout
log4perl.appender.LOG1.layout.ConversionPattern = %d %p >> %m %n

log4perl.appender.screen = Log::Log4perl::Appender::Screen
log4perl.appender.screen.stderr = 0
log4perl.appender.screen.layout = PatternLayout
log4perl.appender.screen.layout.ConversionPattern = %d %p >> %m %n
);

Log::Log4perl::init(\$log_conf);
my $logger = get_logger();

my %args;
GetOptions(
\%args,
'gsg-cmd=s',
'comms-file=s'
);

my $comm_file = "talk.gsgd";
my $LOCK_FILE = "lock.gsgd";
my $regen_cmd;

sub process_args() {

if ( ! defined $args{'gsg-cmd'} || $args{'gsg-cmd'} eq "" ) {
$logger->error("Must pass --gsg-cmd");
exit 1;
}

$regen_cmd = $args{'gsg-cmd'};

if ( defined $args{'comms-file'} ) {
if ( ! -f $args{'comms-file'} ) {
$logger->error("$args{'comms-file'} doesn't look like a regular file");
exit 1;
}

if ( ! -w $args{'comms-file'} ) {
$logger->error("$0 doesn't appear to have permission to write to $args{'comms-file'}");
exit 1;
}

$comm_file = $args{'comms-file'};
}

}

process_args();

sub create_lock() {

$logger->debug("Creating lock file while operating");
open(my $fh, ">", $LOCK_FILE) or die $logger->error("Couldn't create $LOCK_FILE");
print $fh "";
close $fh;

}

sub remove_lock() {

$logger->debug("Removing lock file, not operating");
unlink($LOCK_FILE) or die $logger->error("Couldn't unlink $LOCK_FILE");

}

sub check_lock() {

if ( -f $LOCK_FILE ) {
$logger->info("Found lock file");
sleeper(5);
if ( -f $LOCK_FILE ) {
die $logger->error("$LOCK_FILE still exists even after waiting, why?");
}
}

}


sub remove_instruction($) {

my $instruction_to_remove = shift;

$logger->debug("Removing $instruction_to_remove instruction");
$logger->debug("Opening $comm_file for writing");
open(my $fh, ">", $comm_file);
my @lines = $fh;
foreach my $line ( @lines ) {
# This is bad TODO
print $fh "$line\n" unless ( $line =~ m/$instruction_to_remove/ || $line =~ m/GLOB/);
}
$logger->debug("Closing $comm_file");
close $fh;

}

sub regen() {

$logger->info("Regening site");
system("$regen_cmd") == 0
or die $logger->error("Failed to exec $regen_cmd !");
check_lock();
create_lock();
remove_instruction("Regen");
remove_lock();

}

sub gsgd_exit() {

check_lock();
create_lock();
remove_instruction("Exit");
remove_lock();
exit 0;

}

sub sleeper($) {

my $sleep_time = shift;
$logger->debug("Sleeping $sleep_time seconds");
sleep $sleep_time;

}

sub open_comms() {

$logger->debug("Opening $comm_file for reading");
open(my $fh, "<", $comm_file) or die $logger->error("Could not open $comm_file for reading");
my @instructions = <$fh>;
$logger->debug("Closing $comm_file");
close $fh;

foreach my $line ( @instructions ) {
chomp $line;
if ( $line =~ m/^Regen$/ ) {
$logger->info("Got $line instruction");
regen();
} elsif ( $line =~ m/^Exit$/ ) {
$logger->info("Got $line instruction");
gsgd_exit();
} else {
$logger->error("Unrecognized instruction $line");
}
}

}

$logger->info("Starting");
while() {

sleeper(1);
open_comms();

}