package Policies;
use PDM::Parse;
use strict;
use System;

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

  my $policies = PDM::Parse->parse("System/Policies/$file");
  my $extended = $class->extended();

  my $obj = { policies => $policies, extended => $extended , file => $file};
  bless($obj, 'Policies');

  return $obj;
}

sub sev {
  my($class, $val) = @_;
  if ($val eq "E") {
    return 2;
  } elsif ($val eq "W") {
    return 1;
  } elsif ($val eq "I") { # Informational
    return 0;
  } elsif ($val eq "X") { # no event
    return -1;
  } elsif ($val eq "D") { # Down event
    return 3;
  }
  return 0;
}

# comp1 : disk 
# key   : t3_serial_no:disk.u1d1

sub run {
  my($obj, $err, $lines, $ix, $comp1, $dev_name, $key, $ip, $key0, $known) = @_;

  my $policies = $obj->{policies};
  my $EX       = $obj->{extended};
  my $renv     = System->get_renv();

  my $line = $lines->[$$ix];
  my @Xpattern;
  foreach my $pol (@$policies) {
     my $pat = substr(Util->rtrim($pol->{pattern}),1,-1);
     my $rev_pat = substr(Util->rtrim($pol->{reverse_pattern}),1,-1);
     my @PT;
     if ($line =~ /$pat/ || ($rev_pat && $line =~ /$rev_pat/) ) {
       push(@PT, $1) if ($1);
       push(@PT, $2) if ($2);
       push(@PT, $3) if ($3);
       my $found;
       my $e1 = "$line\n";
       next if ($pol->{known} && !$known);

       if ($pol->{pattern2}) {
           my $p2 = substr($pol->{pattern2}, 1, -1);
           if ($lines->[$$ix+1] =~ /$p2/) {
             push(@PT, $1) if ($1);
             push(@PT, $2) if ($2);
             push(@PT, $3) if ($3);
             $e1 .= $lines->[$$ix+1] . "\n" . $lines->[$$ix+2] . "\n" . $lines->[$$ix+3] . "\n";
             $found++; $$ix += 3;
           }
       }

       if (($pol->{pattern2} || $pol->{pattern3}) && !$found) {
          next;
       }
       my $sev = $pol->{severity};

        if ($sev eq "X") {
          push(@Xpattern, $pat);          
       	  next; 	
       }	       

       my $Xfound;
       if ($Xpattern[0]) {
         for (my $x=0; $x <= $#Xpattern; $x++) {
         my $curXpat = $Xpattern[$x];
           if ($line =~ /$curXpat/) {
             $Xfound = 1;
           }	
         }
       }
       next if ($Xfound);

       if ($pol->{code}) {
          my($pkg, $f) = split(/\:+/, $pol->{code});
          require "Policies/$pkg.pm";
          $pkg = "Policies::$pkg";
          my $extra;
          ($sev,$extra) = $pkg->$f( $pol,$line, $key, $comp1, $sev );
          $e1 .= " $extra";
       }
       if ($pol->{shortkey}) {
          $key  = $key0 . ":$comp1";
       }

       if ($pol->{key}) {
          if ($pol->{key} eq "\$PORT") {
            $key = $key0 . ":port." . ($PT[0]-1);
          } else {
            $key .= "." . $pol->{key};
          }
       }
       my $eg     = $pol->{egrid};

       if ($pol->{extended}) {
          my $section = $pol->{extended};
          my $fo;
          if (($fo=$EX->{$section}{"$PT[0].$PT[1].$PT[2]"})  || 
              ($fo=$EX->{$section}{"$PT[0].$PT[1]"}       )  ||
              ($fo=$EX->{$section}{"$PT[0]"}              )) {
             my $specific = 0;
             if (index($fo,",") >= 0) {
                ($fo, $eg) = split(/\s*,\s*/, $fo); 
                $specific = 1;
             }
             $sev    = $fo;
             $eg    .= $fo if (!$specific);
          }
       }
       
       if ($pol->{threshold}) {
          my $th_type = $pol->{threshold_type} || "device";
          Thresholds->add($obj->{file}, $pol->{_section}, $pol->{threshold});
          my $t_key = $th_type eq "device" ? $key0 : $key;
          my($level, $cnt, $desc, $mins, $thr, $thr_time)= 
              Thresholds->test($obj->{file}, $pol->{_section}, 1, 1, $t_key);
          if ($level eq "E") {
              $sev = $level; 
          } elsif ($level eq "W") {
              $sev = $level;
          } elsif ($level eq "D") {
              $sev = $level;
          } else {
              next;
          }
          my $tx = "[$cnt message(s)";
          $tx .= " in ". sprintf("%.1f", $mins) . " mins" if ($mins && $thr > 1);
          $thr_time .= ($thr_time =~ /h$/) ? "ours":"ins";
          $tx .= " ,threshold is $thr in $thr_time]";
          $e1 = "$tx $e1";
       }

       $sev = $obj->sev($sev);
       my $action;
       $action = 1 if ($sev >= 2);

       next if ($sev < 0); 
       if (!exists $pol->{key}) {
         $key .= "\t$pol->{_section}";
       }

       if ($eg) {
          $eg =~ s/\$comp1/$comp1/;
          $err->[$sev]{$key}{egrid} = $eg;
       }
       Debug->print3("  ($obj->{file}:$pol->{_section}), sev=$sev: $e1") if ($renv->{fsa_debug});
       $err->[$sev]{$key}{action} = $action;
       $err->[$sev]{$key}{section}= "Policies/$obj->{file}:$pol->{_section}";
       if ($rev_pat) {
          my $c1 = ($line =~ /$pat/) ? +1 : -1;
          $err->[$sev]{$key}{total} += $c1;
       }
       $err->[$sev]{$key}{count}++;
       $err->[$sev]{$key}{line}  .= $e1 if ($err->[$sev]{$key}{count} < 100);
       $err->[$sev]{$key}{name}   = $dev_name;
       $err->[$sev]{$key}{priority}= $pol->{priority};
       $err->[$sev]{$key}{ip}     = $ip;
       last;
     }
  }
}


sub extended {
  my($class, $file) = @_;
  my $F = System->get_home() . "/System/Policies/extended_policies";
  my %H;
  my ($l, $section);
  my $cnt=-1;
  if (open(O, $F)) {
    while ($l = <O>) {
      chop($l);
      next if (substr($l,0,1)  eq "#");
      if ($l =~ /^\[(\w+)\]/) {
         $section = $1;
         $cnt++;
      } elsif (index($l, "=") > 0) {
         my($a,$b) = split(/\s*\=\s*/, $l,2);
         $a =~ s/\s+/./g;
         $H{$section}{$a} = $b;
      }
    }
    close(O);
  }

  return \%H;
}


1;

