package Client::Control;
use Client;
use strict;
use Events;
use Debug;
use State;
use Util;

use vars qw ($PRO);

$PRO = "|sae|sunmc|nsm|ssrr|netconnect";

#
# Agent control for ESM health control
#
sub Agent {
  my($q) = @_;
  my $command = $q->{command};
  my $format = $q->{format} || "tab";
  my $key    = $q->{key};
  Debug->logLine("Client::Control::Agent $command $key");

  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();

# If key then enable/disable a single device on the agent.
  if ($key){
    my($type, $key) = split(/\:/, $key);
    foreach my $d (@$devs) {
      if ($type eq $d->{type}) {
	if ($key eq $d->{key}){
	  if ($command){
	    if ($command eq "start") {
	      $d->{active} = "Y";
	    }
	    elsif ($command eq "stop") {
	      $d->{active} = "N";
	    }
	    else {
	      print Client->error($format, 101, "Unknown Command [$command]");
	      return;
            }
            PDM::ConfigFile->write( $renv, $devs, $hosts,$notifs);
	  }
	  print Client->http_OK();
	  if ( "Y" eq $d->{active} ){
	    print "OK start\n";
	  }
	  else {
	    print "OK stop\n";
	  }
	  return;
	}
      }
    }
  }

# Do agent instead of a single device on the agent.
  if ($command){

    if ($command eq "start" || $command eq "stop") {

      my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();
      $renv->{active} = $command eq "start" ? "Y" : "N";
      PDM::ConfigFile->write($renv, $devs, $hosts, $notifs);

    } elsif ($command eq "lock") {
      my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();
      if ($renv->{active} eq "Y") {
	$renv->{active} = "N";
        PDM::ConfigFile->write($renv, $devs, $hosts, $notifs);

	my $exit_value  = system "ps -e | grep rasagent >> /dev/null 2>&1";
	if (0 eq $exit_value){
          $renv->{active} = "Y";
          PDM::ConfigFile->write($renv, $devs, $hosts, $notifs);
	  print Client->error($format, 102, "Agent busy");
	  return;

	}
      }
    }
    else {
      print Client->error($format, 101, "Unknown Command [$command]");
      return;
    }
  }

  print Client->http_OK();
  if ($renv->{active} eq "N") {
    print "OK stop\n";
  }
  else {
    print "OK start\n";
  }
}


#
# Print properties for all the monitored devices.
#
sub GetDevices {
  my($q) = @_;
  my $format = $q->{format} || "xml";

  my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();

  print Client->http_OK();
  print Client->xmlHeader();
  print Client->xmlTag("DEVICES");
  foreach my $d (@$devs) {
    print Client->xmlTag("DEVICE");
    foreach my $x (sort keys %$d) {
      print Client->xmlVALUE($x, $d->{$x});
    }
    print Client->xmlEndTag("DEVICE");
  }
  print Client->xmlEndTag("DEVICES");
}

#
# Print all the slaves.
#
sub GetHosts {
  my($q) = @_;
  my $format = $q->{format} || "xml";

  my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();

  print Client->http_OK();
  print Client->xmlHeader();
  print Client->xmlTag("HOSTS");
  foreach my $h (@$hosts) {
    print Client->xmlTag("HOST");
    foreach my $x (sort keys %$h) {
      print Client->xmlVALUE($x, $h->{$x});
    }
    print Client->xmlEndTag("HOST");
  }
  print Client->xmlEndTag("HOSTS");
}

#
# Add a slave to the master host list.
#
# [host1]
# active=Y
# categories=3510|6120|9900|a3500fc|a5k|brocade|d2|datahost|domain|host|inrange|internal|mcdata|san|se2|se|switch2|switch|t3|tape|v880disk|ve
# frequency=10
# hostid=80d94abc
# hostname=spetest2.central.sun.com
# ip=spetest2.central.sun.com
# ipno=172.20.104.54
# last_push=
# logfile=/var/adm/messages
# role=S
# show_monitored_only=N
# skip_luxadm=0
# t300logfile=


sub AddHost {
  my($q) = @_;
  my $format = $q->{format} || "xml";

  my $ip = $q->{ip};
  if ( ! $ip ){
    print Client->error($format, 100,
			"Missing ip argument.");
    return;
  }

  my $frequency = $q->{frequency} || "10";
  my $active    = $q->{active} || "Y";
  my $role      = $q->{role} || "S";
  my $solution  = $q->{solution} || "N";
  my $logfile   = $q->{logfile} || "/var/adm/messages";
  my $t3logfile = $q->{t300logfile} || "/var/adm/messages.t300";
  my $categories = $q->{categories} || "3510|6120|9900|a3500fc|a5k|brocade|d2|datahost|host|inrange|internal|mcdata|san|se2|se|switch2|switch|t3|tape|v880disk|ve|domain";

  Debug->logLine("Client::Control::AddHost $ip");

  my $ipno = Util->name2ip($ip);

  my($renv, $devs, $host, $notifs) = PDM::ConfigFile->read();

  my %EXIST;
  my $x;
  foreach $x (@$host) {
    $EXIST{$x->{ipno}}= 1;
  }
  if ($EXIST{$ipno}) {
    print Client->error($format, 101,
			"Host already exists.");
    return;
  }
  $x = $#$host + 1;

  $host->[$x]{categories}  = $categories;
  $host->[$x]{_name}       = "host" . ($x+1);
  $host->[$x]{hostname}    = $ip;
  $host->[$x]{ip}          = $ip;
  $host->[$x]{ipno}        = $ipno;
  $host->[$x]{active}      = $active;
  $host->[$x]{role}        = $role;
  $host->[$x]{skip_luxadm} = 1;
  $host->[$x]{frequency}   = $frequency;
  $host->[$x]{logfile}     = $logfile;
  $host->[$x]{t300logfile} = $t3logfile;

  if (!PDM::ConfigFile->write( $renv, $devs, $host,$notifs)){
    print Client->error($format, 102,
			"Error saving host.");
    return;
  }

  my $hostProps = $host->[$x];

  print Client->http_OK();
  print Client->xmlHeader();
  print Client->xmlTag("HOST_ADD");
  foreach my $p (sort keys %$hostProps) {
    print Client->xmlVALUE($p, $hostProps->{$p});
  }
  print Client->xmlEndTag("HOST_ADD");
}

sub RemoveHost {
  my($q) = @_;
  my $format = $q->{format} || "xml";

  my $ip = $q->{ip};
  my $ipno = Util->name2ip($ip);

  Debug->logLine("Client::Control::RemoveHost $ip");

  my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();

  my $index=0;
  foreach my $x (@$hosts) {
    if ( $ipno eq $x->{ipno} ){
      splice(@$hosts, $index, 1);
      if (!PDM::ConfigFile->write( $renv, $devs, $hosts,$notifs)){
	print Client->error($format, 102,
			    "Error removing host.");
	return;
      }
      print Client->http_OK();
      print "OK";
      return;
    }
    $index++;
  }
  print Client->error($format, 101, "No host exists for $ip");
}


#
# Uncontracted command to read environment for StorADE
#
sub GetEnv {
  my($q) = @_;
  my $format = $q->{format} || "tab";

  my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();

  print Client->http_OK();
  print "#<pre>\n";

  foreach my $x (sort keys %$renv) {
    print "$x\t$renv->{$x}\n";
  }
  print "#done";
}

#
# Uncontracted command to set an environment variable for StorADE
#
sub SetEnv {
  my($q) = @_;
  my $format    = $q->{format} || "tab";
  my $propname  = $q->{name};
  my $propvalue = $q->{value};
  my $command   = $q->{command} || "set";

  if (!$propname) {
    print Client->error($format, 100, "Missing argument [name]");
    return;
  }

  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();

  if ("$command" eq "set"){
    if (!$propvalue) {
      print Client->error($format, 101, "Missing argument [value]");
      return;
    }
  }
  else {
    if ($renv->{$propname}){
      delete $renv->{$propname};
    }
  }

  $renv->{$propname} = $propvalue;
  PDM::ConfigFile->write( $renv, $devs, $hosts,$notifs);

  print Client->http_OK();
  print "OK";
}


#
# Commands for getting and setting site info.
#
sub SiteInfo {
  my($q) = @_;
  my $format = $q->{format} || "tab";
  my $command = $q->{command} || "list";

  my($renv, $devs, $hosts,$notifs) = PDM::ConfigFile->read();

  my $plist="customer|contract|ticker|cust_no|site_name|site_address|site_city|site_state|site_zip|site_country|site_contact|site_contact_phone|site_email|production";

  my @props = split(/\|/, $plist);

  Debug->logLine("Client::Control::SiteInfo $command");

  # Update command keeps undefined values the same.
  if ("$command" eq "update") {
    foreach my $p (@props) {
      if ($q->{$p}){
	$renv->{$p} = $q->{$p};
      }
    }
    PDM::ConfigFile->write( $renv, $devs, $hosts,$notifs);
  }

  # Set command will make undefined values undefined so all values need to
  # be set if they will be defined. 
  if ("$command" eq "set") {
    foreach my $p (@props) {
      my $val = $q->{$p};
      if ( $val ){
	$renv->{$p} = $val;
      }
      else {
	$renv->{$p} = undef;
      }
    }
    PDM::ConfigFile->write( $renv, $devs, $hosts,$notifs);
  }

  print Client->http_OK();
  if ("$format" eq "tab"){
    print "#<pre>\n";
    foreach my $p (@props) {
      print "$p\t$renv->{$p}\n";
    }
    print "#done";
  }
  else {
    print Client->xmlHeader();
    print Client->xmlTag("SITE_INFO");
    foreach my $p (@props) {
      print Client->xmlVALUE($p, $renv->{$p});
    }
    print Client->xmlEndTag("SITE_INFO");
  }
}

#
# Make this storade a slave to a master at the given ip address
#
sub setMaster {
  my($q) = @_;
  my $command = $q->{command};
  my $ip = $q->{ip};
  my $format = $q->{format} || "tab";

  Debug->logLine("Client::Control::setMaster $command $ip");

  if ($command eq "slave"){
    if (!$ip){
      print Client->error($format, 102, "Missing argument [ip]");
      return;
    }

    if (open(O, ">" . System->get_home() . "/DATA/MASTER")) {
      print O "$ip";
      close(O);
      my($renv, $devs, $hosts, $notifs) = PDM::ConfigFile->read();
      $renv->{role} = "S";
      print Client->http_OK();
      print "OK\n";
    } else {
      print Client->error($format, 103, "Cannot write to MASTER: $!");
    }
  }
  elsif ($command eq "master") {
    unlink System->get_home() . "/DATA/MASTER";
    print Client->http_OK();
    print "OK";
  }
  elsif ($command eq "push") {
    my $cli =  System->get_home() . "/bin/ras_admin push_config >> /dev/null 2>&1 &";
    Debug->logLine("Client::Agent::setMaster $cli");
    system($cli);

    print Client->http_OK();
    print "OK";
  }
  else {
    print Client->error($format, 101, "Unknown Command [$command]");
    return;
  }
}


sub getProviderSettings {
  my($q) = @_;

  my($renv, $devices, $hosts, $notifs) = PDM::ConfigFile->read();

  Debug->logLine("Client::Control::getProviderSettings");

  print Client->http_OK();
  if ($q->{format} eq "xml") {
    print Client->xmlHeader();
    print Client->xmlTag("PROVIDER_REPORT");

    my %P;
    foreach my $x (sort keys %$renv) {
       if ($x =~ /pro\.([^\.]+)\./) {
          $P{$1} = 1;
       }
    }
    foreach my $pro (sort keys %P) {
       next if (!$pro);
       print Client->xmlTagOpen("PROVIDER");
       print Client->xmlAttrib("ID", $pro);
       print Client->xmlTagClose();
       foreach my $x (sort keys %$renv) {
          my @l = split(/\./, $x);
          next if ($l[2] eq "maxsize");
          if ($l[0] eq "pro" && $l[1] eq $pro) {
	    print Client->xmlVALUE($l[2], $renv->{$x});
          }
       }
       print Client->xmlEndTag("PROVIDER");
    }
    print Client->xmlEndTag("PROVIDER_REPORT");

  } else {
    print "#<pre>\n";
    foreach my $x (sort keys %$renv) {
       my @l = split(/\./, $x);
       next if (index($PRO, $l[1]) < 0);

       if (substr($x,0,4) eq "pro.") {
          print "$x\t$renv->{$x}\n";
       }
    }
    print "#Done.\n";
  }
}

#
#  provider=srs|sunmc|netconnect|http
#  active=Y/N
#  ip=ipnumber
#  frequency=6 (hours hb)

sub setProviderSettings {
  my($q) = @_;
  my $VALID     = "|sunmc|sae|netconnect|";
  my $provider  = $q->{provider};
  my $active    = $q->{active};
  my $frequency = $q->{frequency};
  my $ip        = $q->{ip};

  Debug->logLine("Client::Control::setProviderSettings $provider $active $ip");

  my($renv, $devices, $hosts, $notifs) = PDM::ConfigFile->read();

  if (index($VALID, "|$q->{provider}|") < 0) {
     print Client->error($q->{format}, 301, "Invalid provider ($VALID)");
     return;
  }
  $renv->{"pro.$provider.active"}    = uc($active);
  $renv->{"pro.$provider.ip"}        = $ip       if ($ip);
  $renv->{"pro.$provider.frequency"} = $frequency +0 if (exists $q->{frequency});
  if ($provider eq "sae") { 
    $renv->{"pro.$provider.components"} = $q->{components} if ($q->{components});
    $renv->{"pro.sae.format"}           = 1 if ($q->{format} ne "xml"); # tabs
  }

  if ($provider eq "netconnect") {
      my $maxsize   = $q->{maxsize};
      my $version   = $q->{version};
      if ($maxsize){
	$renv->{"pro.netconnect.maxsize"} = $maxsize;
      }
      if ($version){
	if ($version eq "ANY"){
	  $renv->{"pro.netconnect.version"} = "";
	}
	else {
	  $renv->{"pro.netconnect.version"} = $version;
	}
      }
  }

  PDM::ConfigFile->write( $renv, $devices, $hosts, $notifs);
  Events->saveEvent("PRO", $provider, $active, 
                    $ENV{REMOTE_USER} || $ENV{REMOTE_ADDR} || "unknown" );

  print Client->http_OK();
  if ($q->{format} eq "xml") {
     print <<EOF;
<?xml version ="1.0"?>
<PROVIDER_REPORT>
   <PROVIDER ID=\"$provider\">
EOF
    foreach my $x (sort keys %$renv) {
       if ($x =~ /pro\.$provider\.(.*)/) {
         my $id = $1;
         print "    <VALUE ID=\"$id\">$renv->{$x}</VALUE>\n";
       }
    }
    print "  </PROVIDER>\n</PROVIDER_REPORT>\n";
  } else {
    print "#<pre>\n";
    foreach my $x (sort keys %$renv) {
       if ($x =~ /pro\.$provider\./) {
         print "$x\t$renv->{$x}\n";
       }
    }
    print "#Done\n";
  }
}

# &event=1  : get all avents

sub GetAlarms {
  my($q) = @_;
  my $format = $q->{format} || "tab";
  my $key   = $q->{key};
  my $event = $q->{event}; 
  
  Debug->logLine("Client::Control::GetAlarms");

  require State;
  my $State = State->read();
  my $Comp  = $State->hash();
  my $out;

  print Client->http_OK();
  if ( $q->{format} eq "xml"){
    print "<ALARMS>\n";
  }
  else {
     print "#<pre>\n";
  }

  foreach my $el (keys %$Comp) {
    next if ($key && $el ne $key);
    my $comp = $Comp->{$el};

    foreach my $topic (keys %$comp) {
      my $sev = int($comp->{$topic}[0] + 0.5);
      if (!$event) {
        next if (!$sev || $comp->{$topic}[5] < 0); # skip info-events or sub-events
      }
      my($type, $wwn) = split(/\:/, $el);
      my $desc       = $comp->{$topic}[1];
      my $eh         = State->eventHash($comp->{$topic}[4]);
      my $ack        = $comp->{$topic}[7];  
      my $agg        = $comp->{$topic}[5];  
      $agg = 0 if ($agg < 0);
      my $full_topic;

      if ($eh->{DisplayTopic}) {
         $full_topic = State->clean_topic($eh->{DisplayTopic});

      } else {
         my $cap     = $eh->{Caption};
         $cap        = substr($cap,2) if ($cap =~ /^[MP]\./);
         $full_topic = $cap;

         my $comp    = $eh->{Component};
         if ($comp && index($cap, $comp) < 0) {
           $full_topic .= " - $comp";
         }
         $full_topic = State->clean_topic($full_topic);
      }

      my $ACK ;
      if ($ack->{ack}) {
        $ACK = "<ack>Y</ack>\n<ack_login>" . Client->xmlEncode($ack->{login}) . "</ack_login>\n".
               "<ack_text>" . Client->xmlEncode($ack->{note}) . "</ack_text>\n";
      } else {
        $ACK = "<ack>N</ack>\n";
      }

      my $out1;
      my $parent  = "YES" if ($comp->{$topic}[5] < 0);
      my $devname = $eh->{TargetName} || $eh->{Target};

      if ( $q->{format} eq "xml"){
        $desc = Client->xmlEncode($desc);
        $devname = Client->xmlEncode($devname);
	print "<event>\n";
#  print "<type>$type $comp->{$topic}[5]</type>\n";
   print "<type>$type</type>\n";
  print "<key>$wwn</key>\n";
  print "<topic>$topic</topic>\n";
  print "<full_topic>$full_topic</full_topic>\n";
  print "<severity>$sev</severity>\n";
  print $ACK;
  print "<desc>$desc</desc>\n";
  print "<parent>$parent</parent>\n";
  print "<aggregate>$agg</aggregate>\n";
  print "<parent_id>$eh->{Parent}</parent_id>\n";
  print "<eventType>$eh->{EventType}</eventType>\n";
  print "<deviceName>$devname</deviceName>\n";
  print "<gridCode>$eh->{GridCode}</gridCode>\n";
  print "<ip>$eh->{SourceIP}</ip>\n";
print "</event>\n";
       } else {
          print "$type\t$wwn\t$topic\t$sev\t$desc\t$eh->{EventType}\t$eh->{TargetName}\t$eh->{GridCode}\t$eh->{SourceIP}\n";
       }
     }
  }
  if ( $q->{format} eq "xml"){
    print "</ALARMS>\n";
  }
  else {
     print "#DONE";
  }
}



sub providerHelp {

  print Client->http_OK();

  print <<EOF;
<pre>
GO=Client::Control::getProviderSettings

pro.ssrr.active = Y
pro.ssrr.frequency = 0
pro.ssrr.ip = 172.20.6.124

GO=Client::Control::setProviderSettings&provider=sae&active=Y&ip=1.1.1.1
GO=Client::Control::setProviderSettings&provider=sae&active=Y&ip=1.1.1.1&components=Y
GO=Client::Control::setProviderSettings&provider=srs&active=Y&ip=1.1.1.1
GO=Client::Control::setProviderSettings&provider=srs&active=N
EOF
}
  
1;
