package PPRO;

use System;
use XML::LibXML;
use strict;
use vars qw ($ERROR);

# $ppro = PPRO->parse($sample);
#
# foreach my $dev (@{$ppro->devices()}) {
#   print "\n" . $dev->type() . ", " . $dev->key() . "\n";
#
#   foreach my $patch (@{$dev->patches()}) {
#      print "   patch= $patch->{patchID} : $patch->{synopsis} \n";
#
#      foreach my $fru (@{$patch->frus()}) {
#         print "        fru= $fru->{locator} : $fru->{product}, $fru->{revision} \n";
#      }
#   }
#    my $mess = $ppro->error($patch->{error},"message");
#}

sub add_cdrom {
  my($class) = @_;

  my $renv = System->get_renv();

  if ($renv->{'ppro.source'} eq "CD") {
     return " -c patchpro_cdrom.conf ";
  } 
  return "";
}

sub cli_path {
  return "/opt/SUNWppro/bin/pprosvc";
}
sub setup_path {
  return "/opt/SUNWppro/bin/pprosetup";
}


sub parseFromFile {
  my($class, $file, $trace) = @_;
  my (@l);
  if (open(O, $file)) {
    @l = <O>; close(O);
    return $class->parse("@l", $trace);
  } else {
    $ERROR = "Cannot open $file; $!";
    return undef;
  }
}
  

sub parse {
  my($class, $string, $trace) = @_;
  my $parser = XML::LibXML->new();
  my $P = {};
  bless($P, 'PPRO');
  return $P if (!$string);

  $string =~ s/\&//g;

  my $dom;
  eval {
    $dom   = $parser->parse_string($string);
  };
  $ERROR = $@;
  $ERROR =~ s/</&lt;/g;

  return $P if (!$dom);

  my $elem  = $dom->getDocumentElement();

  foreach my $errorlist ( $elem->findnodes( "errorlist") ) {
    next if ($errorlist->getType() != XML_ELEMENT_NODE) ;
    foreach my $err (  $errorlist->getChildrenByTagName("error") ) {
      next if ($err->getType() != XML_ELEMENT_NODE) ;
      my $message = $err->textContent();
      if ($message) {
	print $message if ($trace);
	$P->{ERRORS} = $message; 	
      }
    }
  }

  foreach my $patchl ( $elem->findnodes( "patchlist")) {
    next if ($patchl->getType() != XML_ELEMENT_NODE) ;
    my $hostType = $patchl->getAttribute("hostType");
    my $hostIp   = $patchl->getAttribute("hostIPAddress");
    my $key = $hostIp;
    $P->{$key}{TYPE} = $hostType;
    $P->{$key}{IPAddress}   = $hostIp;
    print "\npatchlist: $hostType, $hostIp \n" if ($trace);

    foreach my $error ( $patchl->getChildrenByTagName("error") ) {
        my $code = $error->getAttribute("code");
        print "  error code=$code\n" if ($trace);
        foreach my $c ($error->getChildNodes()) {
          next if ($c->getType() != XML_ELEMENT_NODE) ;
          my $name = $c->getName();
          my $text = $c->textContent();
          print "    $code : $text \n" if ($trace);
          $P->{$key}{ERRORS}{$code}{$name} = $text;
        }
    }
    my $pcnt= 0;
    foreach my $patch ($patchl->getChildrenByTagName("patch") ) {
       print "  PATCH:\n" if ($trace);
       my $fcnt = 0;
       foreach my $el ($patch->childNodes()) {
           next if ($el->getType() != XML_ELEMENT_NODE) ;
           my $name = $el->getName();
           if ($name eq "hwIdentifier") {
              print "  Frus:\n" if ($trace);
              foreach my $fruid ($el->childNodes()) {
                 next if ($fruid->getType() != XML_ELEMENT_NODE) ;
                 my $info = $fruid->getName; 
                 my $text = $fruid->textContent();
                 print "     $info : $text\n" if ($trace);
                 $P->{$key}{PATCHES}[$pcnt]{FRUS}[$fcnt]{$info} = $text;
              }
              $fcnt++;  
           } else {
              my $info = $el->getName; 
              my $text = $el->textContent();

              $P->{$key}{PATCHES}[$pcnt]{$info} = $text;
              print "    $info : $text \n" if ($trace);
           }
       }
       $pcnt++;
    }
  }
  bless($P, 'PPRO');
  return $P;
}

# $ppro = PPRO->parse($string);
# $patches = $ppro->getPatches("191.2.2.1");

sub getPatches {
  my($ppro, $key) = @_;
 
  if (exists ($ppro->{$key})) {
     return $ppro->{$key}
  } else {
     return undef;
  }
}

sub keyList {
  my($ppro) = @_;
  my(@list);
  foreach my $el (keys %$ppro) {
    push(@list, $el);
  }
  return \@list;
}

sub devices {
  my($ppro) = @_;
  my(@list, $el);
  foreach my $el (keys %$ppro) {
    my $dev = $ppro->{$el};
    if ($el eq "ERRORS") { # skip the errors (bug 6248878)
    } else {
      $dev->{KEY} = $el;
      bless($dev, 'PPRO_dev');
      push(@list, $dev);
    }
  }
  return \@list;
}



package PPRO_dev;

sub error {
  my ($dev, $code, $val) = @_;
  if ($val)  {
    if (exists( $dev->{ERRORS}{$code}{$val})) {
      return $dev->{ERRORS}{$code}{$val};
    } else {
      return undef;
    }
  } elsif (exists ($dev->{ERRORS}{$code})) {
    return $dev->{ERRORS}{$code};
  } else {
    return undef;
  }
}

sub key {
  my ($dev) = @_;
  return $dev->{KEY};
}

sub type {
  my ($dev) = @_;
  return $dev->{TYPE};
}

sub patches {
  my ($dev) = @_;
  my @l;
  foreach my $p (@{$dev->{PATCHES}}) {
    bless($p, "PPRO_patch");
    push(@l, $p);
  }
  return \@l;
}

package PPRO_patch;

sub frus {
  my($patch) = @_;
  my @l;
  foreach my $f (@{$patch->{FRUS}}) {
    push(@l, $f);
  }
  return \@l;
}

package PPRO_fru;



1;
