use Win32;
use Win32::Daemon;
use Getopt::Long;

our $opt_install;
our $opt_remove;
our $opt_once;

GetOptions("install","remove","once");

### CONFIGURABLE OPTIONS

$SERVICE_SLEEP_TIME = 20; # 20 milliseconds
$PrevState = SERVICE_START_PENDING;

my @FILES = (
	'C:\Documents and Settings\erik\My Documents\moon.txt',
	'C:\Documents and Settings\erik\My Documents\stuff.txt',
);

## SETUP/INSTALL

$Path = $0;
$Cd = `cd`; chomp($Cd);
$Path = $Cd . "\\" . $Path if $Path !~ /\\/;

if ($opt_install) {
    %Hash = (
    	machine		=>  '',
        name    	=>  'MonDate',
        display 	=>  'File Monitor and Date',
        path    	=>  $^X,
        description 	=> 'Monitor text files for changes and mark changes with date/times',
        parameters  	=>	$Path,
    );
    if( Win32::Daemon::CreateService( \%Hash ) )
    {
        print "Successfully added.\n";
    }
    else
    {
        print "Failed to add service: " . Win32::FormatMessage( Win32::Daemon::GetLastError() ) . "\n";
    }
    
    exit 0;
}

if ($opt_remove) {
    if( Win32::Daemon::DeleteService( '', 'MonDate' ) )
    {
        print "Successfully deleted.\n";
    }
    else
    {
        print "Failed to delete service: " . Win32::FormatMessage( Win32::Daemon::GetLastError() ) . "\n";
    }
    
    exit 0;
}

if ($opt_once) {
    MonitorFiles();
    exit 0;
}

### STANDARD LOOP

my %LMTIME;

Win32::Daemon::StartService();

while( SERVICE_STOPPED != ( $State = Win32::Daemon::State() ) )
{
  if( SERVICE_START_PENDING == $State )
  {
      # Initialization code
      Win32::Daemon::State( SERVICE_RUNNING );
      $PrevState = SERVICE_RUNNING;
  }
  elsif( SERVICE_STOP_PENDING == $State )
  {
    Win32::Daemon::State( SERVICE_STOPPED );
  }
  elsif( SERVICE_PAUSE_PENDING == $State )
  {
    # "Pausing...";
    Win32::Daemon::State( SERVICE_PAUSED );
    $PrevState = SERVICE_PAUSED;
    next;
  }
  elsif( SERVICE_CONTINUE_PENDING == $State )
  {
    # "Resuming...";
    Win32::Daemon::State( SERVICE_RUNNING );
    $PrevState = SERVICE_RUNNING;
    next;
  }
  elsif( SERVICE_STOP_PENDING == $State )
  {
    # "Stopping...";
    Win32::Daemon::State( SERVICE_STOPPED );
    $PrevState = SERVICE_STOPPED;
    next;
  }
  elsif( SERVICE_RUNNING == $State )
  {
    # The service is running as normal...
    # ...add the main code here...
    MonitorFiles();        
  }
  else
  {
    # Got an unhandled control message. Set the state to
    # whatever the previous state was.
    Win32::Daemon::State( $PrevState );
  }

      # Check for any outstanding commands. Pass in a non zero value
      # and it resets the Last Message to SERVICE_CONTROL_NONE.
      if( SERVICE_CONTROL_NONE != ( my $Message = Win32::Daemon::QueryLastMessage( 1 ) ) )
      {
        if( SERVICE_CONTROL_INTERROGATE == $Message )
        {
          # Got here if the Service Control Manager is requesting
          # the current state of the service. This can happen for
          # a variety of reasons. Report the last state we set.
          Win32::Daemon::State( $PrevState );
        }
      elsif( SERVICE_CONTROL_SHUTDOWN == $Message )
      {
        # Yikes! The system is shutting down. We had better clean up
        # and stop.
        # Tell the SCM that we are preparing to shutdown and that we expect
        # it to take 25 seconds (so don't terminate us for at least 25 seconds)...
        Win32::Daemon::State( SERVICE_STOP_PENDING, 25000 );
      }
    }
    # Snooze for awhile so we don't suck up cpu time...
    Win32::Sleep( $SERVICE_SLEEP_TIME );
}
# We are done so close down...
Win32::Daemon::StopService();

sub MonitorFiles
{
	my $f;
	for $f (@FILES) {
		my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime)
		   = stat($f);

		next if $mtime == $LMTIME{$f};
		
		my $rename = 0;
		open IN, $f;
		open OUT, ">$f.tmp";
		my $fl = 1;
		while (<IN>) {
			if ($fl && ($_ !~ /^\s*$/)) {
				if ($_ !~ /---/) {
					$_ = "---- " . scalar(localtime($mtime)) . " ----\n" . $_;
					$rename=1;
				}
				$fl = 0;
			}
			if ($_ =~ /^-{3}-*/) {
				if ($_ !~ /[a-z]{3} [a-z]{3}/i) {
					s/[\r\n]+$//;
					s/^----*/----/;
					$_ .= " " . scalar(localtime($mtime)) . " ----\n";
					$rename=1;
				}
			}		
			print OUT $_;

		}
		close OUT;
		close IN;

		if ($rename) {
			rename("$f", "$f.prev") || die $!;
			rename("$f.tmp", $f);
		} else {
			unlink("$f.tmp") if !$rename;
		}
		
		$LMTIME{$f} = $mtime;
	}
}
