#!/usr/bin/env perl
use strict;
use warnings;
use IPC::Open3;
use SMT::Agent::Constants;
use SMT::Agent::Utils;
use XML::Simple;
use UNIVERSAL 'isa';


sub jobhandler
{
  my ($jobtype, $jobid, $args, $verbose) =  @_;

  SMT::Agent::Utils::logger ("jobhandler for patchstatus called", $jobid);
  SMT::Agent::Utils::logger ("patchstatus runs jobid \"$jobid\"", $jobid);

  # check whether this handler can handle requested jobtype
  SMT::Agent::Utils::error ("wrong job handler: \"patchstatus\" cannot handle \"$jobtype\"", $jobid) if ( $jobtype ne "patchstatus" );

  #==  run zypper ==

  my $command = "/usr/bin/zypper";
  my @cmdArgs;
  push (@cmdArgs, "--non-interactive");			
  push (@cmdArgs, "--xmlout");			
  push (@cmdArgs, "list-updates");			
  # do not list packages because packages have the same name as patches
  # this causes conflicts with the xml attribute "name" and overwrites <update> elements in the hash
  push (@cmdArgs, "-t");			
  push (@cmdArgs, "patch");			

  ## perform a refresh of repos and services prior to a patchstatus job
  my @REFcmdArgs = ();
  push (@REFcmdArgs, 'ref');
  push (@REFcmdArgs, '--service');

  (my $REFret, my $REFstdout, my $REFstderr) = SMT::Agent::Utils::executeCommand ( $command, undef, @REFcmdArgs );
  $REFstdout='' if ( $verbose ne "true" );
  $REFstderr='' if ( $verbose ne "true" );

  return (
    stdout => defined ( $REFstdout ) ? $REFstdout : '',
    stderr => defined ( $REFstderr ) ? $REFstderr : '',
    exitcode => $REFret,
    success => 'false',
    message => 'Refreshing the repositories and services failed. Patch status can not be computed.'
  ) if ( $REFret != 0 );

  # only if refresh succeeds: run zypper with list-updates and parse the output
  (my $retval, my $stdout, my $stderr) = SMT::Agent::Utils::executeCommand ( $command, undef, @cmdArgs );

  SMT::Agent::Utils::error ("zypper failed", $jobid) if ( $retval != 0 );


  # parse xml
  my $in;
  eval { $in = XMLin( $stderr,  forcearray=>1 ) };
  SMT::Agent::Utils::error ( "unable to parse zypper xml: $@", $jobid )              if ( $@ );
  SMT::Agent::Utils::error ( "zypper xml contains invalid xml", $jobid ) if ( ! ( isa ($in, 'HASH' )));

  my $patchRecommended = 0;
  my $patchSecurity = 0;
  my $patchOptional = 0;

  my $package = 0;
  my $pkgmanager = 0;

  my $h = $in->{"update-status"}->[0]->{"update-list"}->[0]->{"update"};

  foreach my $hashkey (keys %$h)
  {
      $patchSecurity++    if ( $h->{$hashkey}->{category}   eq "security" );
      $patchRecommended++ if ( $h->{$hashkey}->{category}   eq "recommended" );
      $patchOptional++    if ( $h->{$hashkey}->{category}   eq "optional" );
      $pkgmanager++	  if ( $h->{$hashkey}->{pkgmanager} eq "true" );
  }

  if ( $verbose ne "true" )
  {
    $stdout="";
    $stderr="";
  }

  return (
    stdout => defined ( $stdout )? $stdout : "",
    stderr => defined ( $stderr )? $stderr : "",
    exitcode => $retval,
    success => "true",
    message => "$pkgmanager:$patchSecurity:$patchRecommended:$patchOptional # PackageManager=$pkgmanager Security=$patchSecurity Recommended=$patchRecommended Optional=$patchOptional" 
  );

}

SMT::Agent::Utils::logger ("successfully loaded handler for jobtype \"patchstatus\"");

1;

