#!/usr/bin/perl
#------------------------------------------------------------ 
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------ 
use strict;

use Data::Dumper;
use Getopt::Std;
use POSIX qw(ceil);
use POSIX qw(:sys_wait_h :signal_h :errno_h);

use IO::Handle;

use lib '/app/tools/common/lib';
use lib '/app/tools/rps/lib';
use Common::Assert;
use Common::Log;
use RPS::DB::Item::MechanicalRun;
use RPS::ArtistRoyalty::Process::RunController;
use RPS::RoyaltyRun::Status;



# Allow tuning of the verbosity of our output.
#
my $gVerbosityLevel = 1;


# Parse the command-line options.
#
my %gOptions;
_parseCommandLine(\%gOptions);


# Now, we're going to fork off a child process.
# This way I can tell (and therefore log) whether we exited cleanly or because
# of some exception
#
local $SIG{CHLD} = \&REAPER;
my $gChildIsRunning = 1;
my $gChildExitCode;

my $gChildPID = fork();
if ($gChildPID)
{
    _parent();
}
else
{
    _child();
}


sub _child
{
    # Install a signal handler to catch ctrl-c
    #
    $SIG{INT} = \&CTRL_C;

    
    # Instantiate the application singleton object.
    #
    my $appSingleton = Common::RSApp->new(clientID => $gOptions{clientID});


    # Instantiate the run controller object, then let 'er rip.
    #
    my $controller = RPS::ArtistRoyalty::Process::RunController->new(runID => $gOptions{runID}, logLevel => $gVerbosityLevel);


    my $exitCode = $controller->delete();
    Common::Log::Print("------ IN CHILD PROCESS, CHILD EXIT CODE = $exitCode");
    exit($exitCode);
}


sub _parent
{
    local $SIG{INT} = 'IGNORE';

    while ($gChildIsRunning)
    {
        # We don't want to go nuts polling for the child exit status.
        # Two seconds seems a reasonable interval.
        #
        sleep(2);
    }


    Common::Log::Print("------ CHILD EXIT CODE = $gChildExitCode");

    # The controller (within the child process) is generally responsible for
    # writing all state changes to the run db item.
    # However, if the process is killed externally, or something unexpected happened,
    # then we have a chance here to note that.
    #
    if (0 != $gChildExitCode)
    {
        my $status;

        if (1 == $gChildExitCode)
        {
            $status = RPS::RoyaltyRun::Status::kAborted;
        }
        else
        {
            $status = RPS::RoyaltyRun::Status::kError;
        }

        my $appSingleton = Common::RSApp->new(clientID => $gOptions{clientID});
        my $obj = RPS::DB::Item::ArtistRoyaltyRun->Lookup(artist_royalty_run_id => $gOptions{runID});

        if ($obj)
        {
            $obj->status($status);
            $obj->save();
        }
    }

    exit(0);
}


sub REAPER
{
    my $deadChildPID = waitpid(-1, &WNOHANG);

    if (-1 == $deadChildPID)
    {
        # no child - ignore this
    }
    elsif (WIFEXITED($?))
    {
        # The child really exited.
        # Let's find out why.
        #
        $gChildExitCode = $? >> 8;
        $gChildIsRunning = 0;
    }
    $SIG{CHLD} = \&REAPER;
}


sub CTRL_C
{
    Common::Log::Print("caught a ctrl-c, aborting");
    exit(1);
}


# Pass dates in 'yyyy-mm-dd' format.
#
sub _parseCommandLine
{
    my ($settings) = @_;

    my %opt;
    getopts('r:c:V:', \%opt);

    if (! $opt{r} || ! $opt{c})
    {
        _usage();
        exit(1);
    }
    $settings->{runID} = $opt{r};
    $settings->{clientID} = $opt{c};

    if (defined $opt{V})
    {
        $gVerbosityLevel = $opt{V};
    }
}


sub _usage
{
    print "\nusage: $0 -c client_id -r run_id [-V n]\n";
    print "\n";
    print "Arguments:\n";
    print "\t-c <client_id>\t\tThe client_id of the client to delete\n";
    print "\t-r <run_id>\t\tThe id of the us mechanical run to delete\n";
    print "\t-V <N>\t\t\tVerbosity level - 0 means no output\n";
}

