package Catalog::Health;

use Catalog::RF;
use base 'Catalog::RF';
use strict;

###################################################
#  MAP FILES
#
# Health (map files)
# Author: Christian Cadieux
# Transform back and forth between storade resource files and XML documents.

# Health      : System/Map/*map
#               $map= Catalog::Health->parseFile("System/Map/t3.map");
#               print $map->toText();
# name              = Number,Time,Quiet,Severity,Comment
# driver.SF_OFFLINE = 10,24h,1h,W,COmment
# XML:
# <health_map>
#  <stateChangeEvent class="fruStatus">
#    <change value="ready-enabled" severity=E available=0></change>
#    <start  value="ready" severity=W available=1></change>
#    <transition old="ready" new="offlne" severity=W></transition>
#  </stateChangeEvent>
#  <valueChangeEvent class="time_diff" severity=W available=0></valueChangeEvent>
#  <componentRemoveEvent class=volume severity=W available=0></componentRemoveEvent>
# </health_map>
###################################################

sub info {
  return { ROOT => "health_map",
           hash => { stateChangeEvent => "class",
                     valueChangeEvent => "class",
                 componentRemoveEvent => "class",
                   },
          array => { change => 1, start => 1,
                 transition => 1 }};
}

sub toCatalog {
  my($class, $arg) = @_;
  my $D = System->get_home() . "/System/Map";
  my(%D2);
  opendir(O, $D);
  my @files = readdir(O); closedir(O);
  my $C = System->get_home() .  Catalog->device_path();

  foreach my $f (@files) {
    if ($f =~ /(\w+)\.map$/) {
       my $type = $1;
       my $diag = $class->parseFile("System/Map/$f");
       mkdir "$C/$type",0777 if (!-d "$C/$type");
       open(W, ">$C/$type/health.xml");
       print W $diag->toXML();
       close(W);
    }
  }
}

sub fromCatalog {
  my($class, $arg) = @_;
  my $D = ($arg->{BASE_DIR} || System->get_home()) .  Catalog->device_path();
  chdir $D;
  my @files = `ls */health.xml`;

  my $DATA =  Catalog->system_path() . "/Map/";
  mkdir $DATA,0777 if (!-d $DATA);

  my(%D2);
  foreach my $f (@files) {
     chomp($f);
     my $rep =  Catalog::XML->parseFile("$D/$f", $class->info());
     if (!$rep) {
         print "Error reading Catalog/device/$f\n";
         last;
     }
     my $ix = index($f, "/");
     my $f2 = substr($f, 0, $ix);
     open(W, ">$DATA/$f2.map");
     print W $class->toText($rep);
     close(W);
  }
}


sub parseFile {
  my($class, $file, $arg) = @_;

  my $D = System->get_home();
  if (open(O, "$D/$file")) {
     my @l = <O>; close(O);
     $arg->{file} =  $class->file_name($file);
     return $class->parse(\@l, $class->file_name($file));
  } else {
     $class->err("opening $file: $! \n");
     return undef;
  }
}

sub parse{
  my($class, $array, $file_name) = @_;
  my $out .= "<health_map file=\"$file_name\" revision=\"\$" . "Revision:\$\">\n";
  my $last;
  foreach my $l (@$array) {
    chomp($l);
    if (substr($l,0,1) eq "#") {
        $out .= "<!-- $l -->\n";
        next;
    }
    next if (substr($l,0,1) eq "[");
    
    my($a, $b, $c, $d) = split(/\s*\=\s*/, $l);
    my($a1,$a2) = split(/\./, $a);
    if ($a1 eq "LOWERCASE") {
      $out .= "<info lowercase=\"1\" />\n";

    } elsif ($a1 eq "changeEvent") { # valueChangeEvent
      if ($last) {
        $out .= "</stateChangeEvent>\n" ; $last = "";
      }
      $out .= " <valueChangeEvent class=\"$a2\" severity=\"$c\" available=\"0\" />\n";
    } elsif ($a1 eq "ComponentRemoveEvent") {
      if ($last) {
        $out .= "</stateChangeEvent>\n" ; $last = "";
      }
      $out .= " <componentRemoveEvent class=\"$a2\" severity=\"$c\" available=\"0\" />\n";

    } elsif ($a) {  # stateChangeEvent
      if ($a1 ne $last && $a1 ne "START") {
        $out .= "</stateChangeEvent>\n" if ($last);
        $out .= "\n<stateChangeEvent class=\"$a1\">\n";
        $last = $a1;
      }
      if (index($l, "=>") > 0) {
         my(@a) = split(/\s*[\>\=]+\s*/, $l);
         if ($a[0] eq "START") {
            $out .= "  <start value=\"$a[1]\" severity=\"$a[2]\" />\n";
         } else {
            $out .= "  <transition old=\"$a[0]\" new=\"$a[1]\" severity=\"$a[2]\" />\n";
         }
      } elsif (index($l, "=") > 0) {
         my(@a) = split(/\s*\=\s*/, $l); 
         $out .= "  <change value=\"$a[0]\" severity=\"$a[2]\" available=\"$a[1]\" />\n";
      }
    }
  }
  $out .= "</stateChangeEvent>\n" if ($last);
  $out .= "</health_map>\n";
  my $report =  Catalog::XML->parse($out, $class->info());
  bless($report, "Catalog::Health");
  return $report;
}

sub toText {
  my($class, $map) = @_;
  $map = $class if (ref($class));
  my $rep = $map->{health_map};
  my($out);
  foreach my $el (sort keys %$rep) {
    my $v = $rep->{$el};
    if ($el eq "valueChangeEvent") {
       foreach my $el2 (sort keys %$v) {
          next if (substr($el2,0,1) eq "_");
          $out .= sprintf("%-35s = 0 = %s\n",
                     "changeEvent.$el2",$v->{$el2}{_ATT}{severity});
       }

    } elsif ($el eq "componentRemoveEvent") {
       foreach my $el2 (sort keys %$v) {
          next if (substr($el2,0,1) eq "_");
          $out .= sprintf("%-350s = 0 = %s\n",
                    "ComponentRemoveEvent.$el2", $v->{$el2}{_ATT}{severity});
       }

    } elsif ($el eq "stateChangeEvent") {
       foreach my $el2 (sort keys %$v) {
          next if (substr($el2,0,1) eq "_");
          my $v2 = $v->{$el2};
          my $start   = $v2->{start};
          my $trans   = $v2->{transition};
          my $changes = $v2->{change};
          $out .= "\n";     
          foreach my $ch (@$changes) {
             $out .= sprintf("%-35s = %s", $ch->{_ATT}{value}, $ch->{_ATT}{available});
             $out .= " = " . $ch->{_ATT}{severity} if ($ch->{_ATT}{severity});
             $out .= "\n";
          }
          foreach my $ch (@$start) {
             $out .= sprintf("START => %-30s = %s\n", $ch->{_ATT}{value}, $ch->{_ATT}{severity});
          }
          foreach my $ch (@$trans) {
             $out .= sprintf("%-35s => %-35s = %s\n", $ch->{_ATT}{old}, 
                             $ch->{_ATT}{new}, $ch->{_ATT}{severity});
          }
       }
    }
  }
  return $out;
}




1;
