#!/usr/local/bin/perl -w

# exportUpdate
# determine which, if any, Remedy objects have been updated since the last run
#  and update the output files based upon findings
#
# parameters
#  server        => Remedy server name
#  username      => Remedy username (should be an Admin)
#  password      => Remedy username password
#  ARTCPPORT     => AR TCP PORT for connection (optional)
#  rootDirectory => root level of output tree

use strict;
use Getopt::Long;
use File::Basename;
use FileHandle;
use integer;	# integer arithmetic is faster
use Time::Local;

BEGIN {
  require 'ar.ph';
}
use remedyExport;
#use lib "$root/cgi-bin";
use ARS;	# ARSperl API
#use DumpVar;
#use Web;
#use lib "$root/private/cgi-bin";
#use ARSesi;	# ARSperl API
#no lib "$root/private/cgi-bin";
#no lib "$root/cgi-bin";

my $ctrl;
my %fields = (
  evDate   =>         3,
  evType   =>       800,
  exported => 600000295,
  ID       =>         1,
  object   =>       802,
);
my $outFile = '/tmp/'. basename( $0 ). '.'. $$;
my %types = (
  &ARS::AR_SVR_EVENT_CHG_SCHEMA    => '-schema',
  &ARS::AR_SVR_EVENT_CHG_CHARMENU  => '-charmenu',
  &ARS::AR_SVR_EVENT_CHG_FILTER    => '-filter',
  &ARS::AR_SVR_EVENT_CHG_ACTLINK   => '-activelink',
  &ARS::AR_SVR_EVENT_CHG_ESCAL     => '-escalation',
  &ARS::AR_SVR_EVENT_CHG_CONTAINER => [ '-application',
                                        '-guideActivelink',
                                        '-guideFilter',
                                        '-packingList',
                                        '-webservice' ],
);

{
  autoflush STDOUT, 1;	# make sure data written to STDOUT is immediately flushed

  # get the command line parameters

  my $arTcpPort;
  my $server;
  my $user;
  my $pass;
  my $rootDir;
  if( !GetOptions( 'ARTCPPORT=i'     => \$arTcpPort,
                   'server=s'        => \$server,
                   'username=s'      => \$user,
                   'password=s'      => \$pass,
                   'rootDirectory=s' => \$rootDir )) {
    die "Error reading command line parameters\n";
  }
  if(( !defined( $server )) || ( !defined( $user )) || ( !defined( $pass )) ||
     ( !defined( $rootDir ))) {
    die "Usage:\n",
        "$0 requires the following parameters:\n",
        "  -server <serverName>\n",
        "  -username <userName>\n",
        "  -password <password>\n",
        "  -rootDirectory <rootDirectory>\n",
        " Optional parameter:\n",
        "  -ARTCPPORT <portNumber>\n",
        "No others are allowed\n";
  }

  # connect to Remedy

  if( defined( $arTcpPort )) {
    $ENV{ARTCPPORT} = $arTcpPort;
  }
  $ctrl = &ars_Login( $server, $user, $pass );
  if( !defined( $ctrl )) {
    die "Unable to connect to Remedy server '$server'\n";
  }

#  my %fieldList = &getFields( $ctrl, 'Server Events', undef, values( %fields ));

  my $NOT_EXPORTED = "'$fields{exported}'=\$NULL\$ AND ";

  # find all unprocessed records doing an import

  my $timestamp = time();
  my $query = $NOT_EXPORTED. "'$fields{evDate}'<$timestamp AND ";
  my( $p_existing, @error ) =
   &getRecords( $ctrl, 'Server Events',
                $query. "'$fields{evType}'=". &ARS::AR_SVR_EVENT_CHG_IMPORT,
                $fields{ID}, [ $fields{evDate} ], { validate  => 0 } );
  if( @error ) {
    die join( "\n", $p_existing, @error ), "\n";
  }
  if( keys( %{$p_existing} )) {
    &execute( $server, $user, $pass, $rootDir );
    &setExported( $timestamp );
  }

  for( ;; ) {
    $timestamp = time();
    my $typeQueryLoop = my $typeQuery =
     $NOT_EXPORTED. "'$fields{evDate}'<$timestamp";
    my @toProcess;
    my $loop = 1;
    while( $loop ) {
      ( $p_existing, my @error ) =
       &getRecords( $ctrl, 'Server Events', $typeQueryLoop, $fields{evType},
                    [ $fields{evType} ], { maxCount  => 1, validate  => 0 } );
      if( @error ) {
        die join( "\n", $p_existing, @error ), "\n";
      }
      if( $loop = keys( %{$p_existing} )) {
        my $key = ( keys( %{$p_existing} ))[0];
        $typeQueryLoop .= " AND '$fields{evType}'!=$key";
        push( @toProcess, $key );
      }
    }
    if( !@toProcess ) {
      last;
    }
    @toProcess = sort { $a <=> $b }( @toProcess );

    # process each type separately

    foreach( @toProcess ) {
      my $loop = 1;
      while( $loop ) {
        $query = $NOT_EXPORTED. "'$fields{evDate}'<". time().
                 " AND '$fields{evType}'=$_";
        ( $p_existing, @error ) =
         &getRecords( $ctrl, 'Server Events', $query, $fields{ID},
                      [ $fields{object} ],
                      { maxCount => 100, validate => 0, showMaxReached => 1 } );
        if( @error ) {
          die join( "\n", $p_existing, @error ), "\n";
        }

        if( $loop = keys( %{$p_existing} )) {
          if( defined( $types{$_} )) {
            my %list;
            foreach( keys( %{$p_existing} )) {
              $list{${$p_existing}{$_}{$fields{object}}} = 1;
            }
            &execute( $server, $user, $pass, $rootDir, $types{$_},
                      keys( %list ));
          }
          &setExported( undef, keys( %{$p_existing} ));
          sleep( 5 );
        }
      }
    }
  }
  exit;
}

sub execute {
  my( $server, $user, $pass, $rootDir, $type, @objects ) = @_;

  my @types = ( defined( $type ) ? $type : '' );
  if( ref( $type ) eq 'ARRAY' ) {
    @types = @{$type};
  }
  foreach( @objects ) {
    $_ = "-object \"$_\"";
  }

  my $cmd = "remedyExport -server $server -username $user -password $pass ".
                         "-rootDirectory $rootDir @types @objects -updating ".
                         "2>$outFile";
  print $cmd, "\n";
  print `$cmd`;
  my $status = $?;

  if( !-z "$outFile" ) {
    print STDERR `cat $outFile`;
    unlink( $outFile );
    die basename( $0 ). " aborted\n";
  }
  unlink( $outFile );

  if( $status ) {
    die "Error running resolveExport: $status\n";
  }

  return;
}

sub setExported {
  my( $timestamp, @keys ) = @_;


  if( defined( $timestamp )) {
    my $query = "'$fields{exported}'=\$NULL\$ AND ".
                "'$fields{evDate}'<$timestamp";
    my( $p_existing, @error ) =
     &getRecords( $ctrl, 'Server Events', $query, $fields{ID},
                  [ $fields{ID} ], { validate  => 0 } );
    if( @error ) {
      die join( "\n", $p_existing, @error ), "\n";
    }
    @keys = keys( %{$p_existing} );
  }

  foreach( @keys ) {
    my $ret = &ars_MergeEntry( $ctrl, 'Server Events', 4,
                               $fields{ID}, $_, $fields{exported}, 0 );
    if(( defined( $ars_errstr )) && ( length( $ars_errstr ))) {
      die "Error modifying 'Server Events' record:\n",
          $ars_errstr, "\n",
          "$0 aborted\n";
    }
  }

  return;
}
