package Diag;
use strict;

# type : t3
# $af  : ($err,$af) = AutoForm->new("System/Tests", {noInfo => 1});
# selected_test: switchtest
# Hdev : node from topology.
# comp : e
# arg->{mode} = 'html';
# arg->{mode} = 'list' # default

sub register_list {
  my($class, $type, $af, $selected_test, $Hdev, $comp, $arg ) = @_;

  my $c2 = $af->commandByName($selected_test);
  my $mode = $arg->{mode} || 'list';
  my $c2_info = $c2->info();
  return () if (!$Hdev);
  my $ports = $Hdev->portInfo();
  my ($node, $reg_select, $all, $cn, $p);
  my $class0 = $Hdev->class0();

  my $fru_type = $c2_info->{fruType};
  my $cn = 0;
  my($node);
  my($all, $first);
  my $multiple = "multiple";
  if (index(",sp,host,", ",$type,") >= 0) {
     if ($c2_info->{node} eq "oob") {       # oob test, use IP
       $reg_select = " ";
       $cn = -1;

     } elsif ($c2_info->{node} eq 'd') {  # device-disk
        $node = "disk";
        ($reg_select, $all, $cn) = &select_devs($Hdev, $mode);

     } else {
       $node = "hba";
       for ($p=0; $p <= $#$ports; $p++) {
          my $pi = $ports->[$p];
          next if (
                 ($fru_type ne substr($pi->{RegisterName},0,length($fru_type))) &&
                 ($pi->{path} !~ /$fru_type/)
          ) ;
          # Don't add qlc soc paths to plain soc paths
          next if(($fru_type eq "soc") && ( $pi->{path}  =~ /qlc/));

          if ($comp eq "e" || substr($comp,0,1) eq "h" ) {
             my $r = $pi->{RegisterName} || $pi->{path};
             my $path = Util->ltrim($pi->{path});
             my($board, $slot, $port) = split(/\:/, $pi->{BoardSlotPort});
             my $extra = "Board$board, Slot$slot, Port$port" if ($board);
             my $v = "$extra $r ($p)";
             my $o = "$p:$path";
             if (substr($comp, 1) eq $p) {
                $first = ($mode eq "list")? "$o=$v\t" : "<option selected value=\"$o\">$v</option>\n";
             } else {
                $reg_select .= ($mode eq "list") ? "$o=$v\t" : "<option value=\"$o\">$v</option>\n";
             }
             $cn++;
             $all .= "$o\t";
          }
       }
       $reg_select = $first . $reg_select;
     }
   } elsif ($c2_info->{node} eq "oob") {       # oob test, use IP
     $reg_select = " ";
     $cn = -1;

   } elsif ($class0 eq "switch") {  # switch or vicom
     $node = "port";
     if ($c2_info->{node} eq 'd') {  # device-disk
        $node = "disk";
        ($reg_select, $all, $cn) = &select_devs($Hdev);

     } elsif ($c2_info->{node} eq 'v') {       # volumes
         $node = "port";
         ($all, $reg_select, $cn) = &getVolInfo($Hdev, $mode);
     } else {
       for ($p=0; $p <= $#$ports; $p++) {
          my $pi = $ports->[$p];
          next if(!exists($pi->{sw_PortNum}) && !exists($pi->{PortNumber})  );
          my $port_type;
          if ((!$pi->{sw_PortType}) ||($pi->{sw_PortType} =~ /ERROR/) ){
            $port_type = "UNKNOWN PORT TYPE/ENTER PASSWORD and CREATE A NEW SNAPSHOT";
          }else{
            $port_type = $pi->{sw_PortType};
          }

          if ($comp eq "e" || substr($comp,0,1) eq "p") {
            my $v = "port$p / $port_type";
            my $fc = $pi->{sw_remote_fcaddr} || $Hdev->info("sw_remote_fcaddr");
            my $ip = $pi->{sw_ipAddr_remote} || $Hdev->info("sw_ipAddr_remote");
            my $o = "port$p:$p:$ip:$fc";
            if (substr($comp, 1) eq $p) {
              $first = ($mode eq "list") ? "$o=$v\t" : "<option selected value=\"$o\">$v</option>\n";
            } else {
              $reg_select .= ($mode eq "list") ? "$o=$v\t" : "<option value=\"$o\">$v</option>\n";
            }
            $cn++;
            $all .= "$o\t";
          }
       }
       $reg_select = $first . $reg_select;
     }

     } else { # storage
      if ($c2_info->{node} eq 'v') {       # volumes
         $node = "port";
         ($all, $reg_select, $cn) = &getVolInfo($Hdev, $mode);

      } elsif ($c2_info->{node} eq 's') {       # device-port
        $node = "port";
        my $ports = $Hdev->portInfo();
        for ($p=0; $p <= $#$ports; $p++) {
          my $pi = $ports->[$p];
          my $p0 = $p+1;
          if ($comp eq "e" || substr($comp,0,1) eq "s") { #  eq "s$p0") 
            #&set_logical_path($pi);
            next if (!$pi->{LogicalPath});
            my @L2 = split(/\|/, $pi->{LogicalPath});
            foreach my $log (@L2) {
              my $v = "port$p:$log";
              my $ix = rindex($log, "/");
              # THIS IS WHERE THE REGISTER LINE IN THE GUI GETS SET
              my $v2;
              if ($type eq "tape") {
                my $devnum = substr($log, $ix+1);
                $devnum =~ s/n/l/;
                $v2 = "/dev/rmt/". $devnum;               
              } else {
                $v2 = $Hdev->portLabel($p) . " (p$p) " . substr($log, $ix+1);
              }

              
              if (substr($comp, 1) eq $p+1) {
                $first .= ($mode eq "list")? "$v=$v2\t" : "<option selected value=\"$v\">$v2</option>\n";
              } else {
                $reg_select .= ($mode eq "list")? "$v=$v2\t" : "<option value=\"$v\">$v2</option>\n";
              }
              $cn++;
              $all .= "$v\t";
            }
          }
        }
        $reg_select = $first . $reg_select;

     } elsif ($c2_info->{node} eq 'd') {  # device-disk
        $node = "disk";
        ($reg_select, $all, $cn) = &select_devs($Hdev, $mode);
     }
  }
  chop($all) if (substr($all,-1) eq "\t");
  my $len = length($all);
  my $all_reg = "";
  my $all_cnt=1;
  my $MAX = 300;
  while (($all_cnt-1) * $MAX < $len) {
    my $sub = substr($all, ($all_cnt-1) * $MAX, $MAX);
    $all_reg .= "<input type=hidden name=all_registers" . sprintf("%3.3d",$all_cnt) . " value=\"$sub\">\n";
    $all_cnt++;
  }

  return ($cn, $reg_select, $all, $all_reg, $node, $multiple);
}

sub getVolInfo {
  my($Hdev, $mode) = @_;
  my ($reg_select, $all);
  my $vols = $Hdev->volInfo();
  my $cn = 0;
  my $pcnt= 1;
  foreach my $logical (sort keys %$vols) {
    my $pi = $vols->{$logical};
    my $v = "port$pcnt:$logical";
    my $log = $logical;
    $log =~ s/\/dev\/rdsk\///;
    my $v2 = "$log";
    $v2 .= ":$pi->{PortMode}" if ($pi->{PortMode});
    $v2 .= ":$pi->{dev_name}" if ($pi->{dev_name});

    $reg_select .= ($mode eq "list") ? "$v=$v2\t" : "<option value=\"$v\">$v2</option>\n";
    $cn++; $pcnt++;
    $all .= "$v\t";
  }
  return ($all, $reg_select, $cn);
}


sub select_devs {
  my($Hdev, $mode) = @_;
  my ($reg_select, $all, $cn);
  my $disks = $Hdev->diskInfo();
  my($d,@D);
  if (ref($disks) eq "HASH") {
    foreach $d (sort keys %$disks) {
      push(@D, "$disks->{$d}{devID}=$d");
    }
  }
  my(@LIST);
  foreach $d (sort @D) {
     my($a1,$a2) = split(/\=/, $d);
     my $reg = $disks->{$a2}{RegisterName};
     my $logical_group = $disks->{$a2}{LGroup};

     #&set_logical_path($disks->{$a2});
     my @L2 = split(/\|/, $disks->{$a2}{LogicalPath});

     foreach my $log (@L2) {
       my $v = "$a1:$log";
       my $ix = rindex($log, "/");
       my $v1 ;
       if ( ($logical_group =~ /Internal/) || (length($a1) < 1) ) {
           $v1 = substr($log, $ix+1);
       } else {
           $v1 = "$a2 " . substr($log, $ix+1);
       }
       push(@LIST, "$v1\t$v\t$reg");
     }
  }
  foreach my $e (sort @LIST) {
     my($v1, $v, $reg) = split(/\t/, $e, 3);
     $reg_select .= ($mode eq "list") ? "$v=$v1\t" :
                                "<option value=\"$v\">$v1 / $reg</option>\n";
     $cn++;
     $all .= "$v\t";
  }
  return ($reg_select, $all, $cn);
}



sub run {
  my($class, $af, $host, $q, $af_test, $selected_test, $to, $dev, $enc) = @_;
 
   my $renv = System->get_renv();
   $host = $renv->{hostname} if ($host eq Util->name2ip());
   my($type, $key, $comp) = split(/\:/, $enc);

   my $email = $af->getOption("#EMAIL", $q);
   my $concurrent = $af_test->info("concurrent") if ($af_test);
   my($pre_err, $pre_data, $tmp, $tmp_err);

    ($pre_err, $tmp) = $class->validation($af_test, $selected_test, $to, $dev, 
                                          $q, "postForm", "Test cannot start");
    # call the pre_form to get the appropriate pre_data #fix for bug 4532928

    ($tmp_err, $pre_data) = $class->validation($af_test, $selected_test,
                         $to, $dev, $q, "preForm", "Warning");

    return ($pre_err, undef, undef) if ($pre_err);

    my($err, $test_command, $opts, $opts_o) = $af->makeCommand($selected_test, $q, 1);

    if ($q->{register} =~ /\[ALL\]/) {
       $q->{register} = "";
       foreach my $x (sort keys %$q) {
         if (substr($x,0,13) eq "all_registers") {
            $q->{register} .= $q->{$x};
         }
       }
    }

# $af->getOption can return 0 which means run Forever
# if it does return 0, don't set it to 1 as it was done below
#   my $passes = $af->getOption("#PASSES", $q) || 1; 
   my $passes = $af->getOption("#PASSES", $q) ;

    my @L = split(/\t/, $q->{register});
    my($ports, $registers);

    foreach my $l (@L) {
       my($port, $reg) = split(/\:/, $l,2);
       $ports     .= "$port\t";
       $registers .= "$reg\t";
    }

   if ($type eq "tape") {
     $registers =~ s/n/l/;
   }

    chop($registers) if ($registers);
    chop($ports)     if ($ports);

    if ($q->{ACTION} =~ /Command/) {
        my $o = $opts_o;
        $o =~ s/passwd=[^\s\=\|]+//;
        $o =~ s/\|/| /g;
        $o = "-o dev=" . $registers . "|" . substr($o,2) if($o !~ /dev=/);
        $o = "-o \"" . substr($o,2) . "\"";
        return (undef, undef,  "'$test_command $opts $o' on '$host'");
    }
    my $last_diag = Util->deserialize("CACHE/last_diag_run") || {};
    $last_diag->{$dev->name()} = time;
    Util->serialize("CACHE/last_diag_run", $last_diag);
    my($err, $pid);
    ($err,$pid) = Scheduler->run('ST', $host, $test_command, "$opts $opts_o",
                $registers, $concurrent, 0, $email, $passes,
               {
                 ports    => $ports,
                 target    => $dev->boxName(),
                 dev_type => $type,
                 node     => $q->{node},
                 key      => $key,
                 comp     => $comp,
               }, 10);

    return (undef, $err, undef, $pid, $test_command, $opts);

}


sub validation {
  my($class, $command, $selected_test, $to, $dev, $q, $type, $header, $quiet) = @_;
  my($pre_err, $pre_data, $gen_pre_data);
  my $module  = $command->info("validation_module");
  my $found = 0;
  
  if ($module) {
    $module = "Tests::$module";
    my $err = Modules->loadOne($module);
    if ($err) {
     return ("Error loading $selected_test: $err", undef);
    }

    foreach my $c ("${selected_test}_$type", $type) {

      if ( $module->can($c)) {
        
        ($pre_err, $pre_data) = $module->$c($command, $to, $dev, $q);
        if($pre_err || ($c =~ /preform/)){
           # if no error, still want to check general rules below
           return ($pre_err? "$pre_err": undef, $pre_data);
        }
        last;
      }
    }
  }
  $module = "Tests::General";
  my $err = Modules->loadOne($module);
  if (!$err) {
     my $c = $type;
     if ( $module->can($c)) {
       ($pre_err, $gen_pre_data) = $module->$c($command, $to, $dev);
       if($pre_err){
          return ("$header: $pre_err");
       }
     }
  }
  if($pre_data){
     return(undef, $pre_data);
  }
  if($gen_pre_data){
     return(undef, $gen_pre_data);
  }
  return (undef,undef);
}




1;



  

