package Transition;
#<copyright>
# ----------------------------------------------------------
# Sun Proprietary/Confidential Code
# Copyright 2001, Sun Microsystems, Inc. All rights reserved.
# ----------------------------------------------------------
#</copyright>

use PDM;
use System;

use strict;

use vars qw ($DB);

###########################################################
#  uses the CACHE
#  TRANSITION STUFF
#  Will keep track of the value of an attribute and return
#  ON if a transition occured, OFF if the value changed
#  and ON_AGAIN if it's been $repeat hours and it's still bad.
#
#
#  Ex: t300:diag230.status = 'CC'

#  $key   (t300:diag230) : how to save this information in the cache
#  $code  (status      ) : name of this attribute
#  $value ('CC'        ) : current value of the attribute
#  $tran_value ('CC'   ) : transition value , can be a ARRAYREF
#  $repeat('24h'|'60m' ) : how long to wait before repeating the same info.
#  severity => [WARNING, ERROR], severit

#  Returns: IN      : In the transition.
#           IN_AGAIN: Still in for $repeat time.
#           LOST    : Lost comunication, nothing to report
#           OUT     : Out of the transition.
#           ""      : All fine, noithing to report.
#
###########################################################

sub read {
  my($class, $key, $code) = @_;
  $DB    = RasDB->new("CACHE");
  my $h  = $DB->hash();
  $code  = "status" if (!$code);

  return $h->{"transition.$key.$code"};
}

sub getTransition {
  my($class,  $arg) = @_;
  my($t, $now);

  $DB    = RasDB->new("CACHE");
  my $h  = $DB->hash();
  my $code   = "transition.$arg->{key}.$arg->{code}";
  my $value  = $arg->{value} ;
  my $tran_value = $arg->{transition_value};
  my $repeat = $arg->{repeat};

  if ($repeat && $repeat !~ /\d+h/ && $repeat !~ /\d+m/) {
    Debug->print2("getTransition: repeat has invalid format: $repeat");
    $repeat = "1d";
  }
  $now = int(time/60);

  my $el = $h->{$code};

  if (&set_equals($value, $tran_value) ) {  # comm lost.
     if (!$el || $el->{value} ne $value)  { # transition
        $h->{$code} = { value => $value, time => $now, iter => 0 };
        return wantarray? ("IN",0, 0) : "IN";

     } elsif ($el->{value} eq $value) { # still IN
        $el->{in_a_row_repeat}++;
        if ($repeat) {
           $t = ($repeat =~ /\d+h/)? $repeat * 60: $repeat+ 0;
           if ($now - $el->{time} > $t) {
              $el->{time} = $now;
              $el->{iter}++;
              return wantarray? ("IN_AGAIN",$el->{iter}, $el->{in_a_row_repeat}) : "IN_AGAIN";
           }
        }
        $h->{$code} = $el;
     }
     return wantarray? ("LOST",$el->{iter}, $el->{in_a_row_repeat}) : "LOST";

  } else {  # communication present
     $el->{in_a_row_repeat} = 0;
     if (!$h->{$code}) {
        $h->{$code} = { value => $value, time => $now, iter => 0};
        return wantarray? ("",0,0) : "";

     } elsif (&set_equals($el->{value}, $tran_value) ) { # OUT
        $h->{$code} = { value => $value, time => $now, iter => 0};
        return wantarray? ("OUT",0, 0) : "OUT";
     }
  }

  return wantarray? ("",0,0) : "";
}

# transition with 2 boolean values (in and out)

sub getTransition2 {
  my($class,  $arg) = @_;
  my($t, $now);
  $DB    = RasDB->new("CACHE");
  my $h  = $DB->hash();

  my $code   = "transition.$arg->{key}.$arg->{code}";

  my $in_value = $arg->{in_value} ? "in" : "F";
  my $out_value= $arg->{out_value}? "out": "F";
  my $repeat   = $arg->{repeat};

  if ($repeat && $repeat !~ /\d+h/ && $repeat !~ /\d+m/) {
    Debug->print2("getTransition: repeat has invalid format: $repeat");
    $repeat = "1d";
  }
  $now = int(time/60);

  my $el = $h->{$code};

  if ($in_value eq "in") {  # comm lost.
     if (!$el || $el->{value} ne $in_value)  { # transition
        $h->{$code} = { value => $in_value, time => $now, iter => 0};
        return wantarray? ("IN",0) : "IN";

     } elsif ($el->{value} eq $in_value) { # still IN
        if ($repeat) {
           $t = ($repeat =~ /\d+h/)? $repeat * 60: $repeat+ 0;
           if ($now - $el->{time} > $t) {
              $el->{time} = $now;
              $el->{iter}++;
              $h->{$code} = $el;
              return wantarray? ("IN_AGAIN",$el->{iter}) : "IN_AGAIN";
           }
        }
     }
     return wantarray? ("LOST",$el->{iter}) : "LOST";

  } elsif ($out_value eq "out") {  # out of the transition
     if (exists($h->{$code}) && $el->{value} ne $out_value)  { # transition
       $h->{$code} = { value => $out_value, time => $now, iter => 0};
       return wantarray? ("OUT",0) : "OUT";
     }
  }
  return wantarray? ("",0) : "";
}



# true if val is in set
sub set_equals {
  my($val, $set) = @_;
  my($i);

  if (ref($set) eq "ARRAY") {
    foreach $i (@$set) {
      return 1 if ($val eq $i);
    }
    return 0;
  } else {
    return ($val eq $set);
  }
}



1;

