# $Id: COMMON.pm,v 1.3 2004/12/20 16:52:32 jkremer Exp $
# Copyright 2004 Sun Microsystems, Inc., All Rights Reserved.
# Sun Proprietary/Confidential: For Internal Use Only
package TO::COMMON;

use strict;
use base 'TO::STORAGE';
use Catalog::Implementation;

sub new {
  my($class, $type) = @_;
  my $this = { type => $type };

  bless($this, "TO::COMMON");
  return $this;
}


sub type {
  my ($this) = @_;
  if (ref($this) eq "TO::COMMON"){
	 return $this->{type};
  }
  return "COMMON";
}

sub leaf {
  my ($this) = @_;
  if (ref($this) eq "TO::COMMON"){
	 return 1;
  }
  return 0;
}

sub isKnownDevice {
  my($this, $dev) = @_;

  my $type = $this->type();
  return if ("COMMON" eq $type);

  my $impl = new Catalog::Implementation($type);
  my $topo = $impl->getFramworkProperty("Topology");
  if (!$topo){
	 return 0;
  }
  eval {
	 my $props = $topo->{property}->{isKnownDevice}->{property};
	 if ($props){
		foreach my $prop (keys %$props){
		  next if ("_ATT" eq $prop);
		  my $val = $props->{$prop};
		  if ($dev->{$prop} eq $val){
			 return 1;
		  }
		  if ($dev->{$prop} =~ $val){
			 return 1;
		  }
		}
	 }
  };
  return 0;
}


# return topo port number for a given topo port.
# sort by port ids.
sub topoPort {
  my( $node, $portWWN, $hba, $Config, $devs, $dev_no) = @_;
  $DB::single=1;

  # Sort portInfo->Id and return index number.
  my $portInfo = $node->{portInfo};
  my $pids = {};
  my $x;
  for ($x = 0; $x <= $#$portInfo; $x++){
	 my $pid = $portInfo->[$x];
	 $pids->{$pid->{Id}} = $pid->{LocalPortWWN};
  }
  $x = 1;
  foreach my $id (sort keys %$pids){
	 if ($portWWN eq $pids->{$id}){
		return $x;
	 }
	 $x++;
  }
  return 0;
}


# return the topo object in DATA/topo
# { 
#  port [undef, connect, undef, undef]
#  portInfo [{PortWWN, Id, LocalPortWWN},{}]
#  info {
#   release, mgmtLevel, name, class, bitMode, ipno, hostid, type, model,
#   host, host_type, name, hosts[], NodeWWN, port_cnt, hosts_type[],
#     VenderID, class, LGroup, type, BoxName
#  }
#
# } 
sub newFromDev {
  my($this, $to, $dev, $arg) = @_;

  my $renv   = System->get_renv();
  my $host   = $renv->{hostname};
  my $k      = $dev->{type} . ":" . $dev->{key};
  my $exists = $to->nodeByName($k);

  my $storages = $to->[2];
  my $key      = $dev->{key};
  my $type     = $dev->{type};
  my $impl     = new Catalog::Implementation($this->type());
  my $info     = $impl->getInfo();

  my $obj = $exists || {};
  my $org_name          = $obj->{info}{name};
  $obj->{info}{type}    = $type;
  $obj->{info}{class}   = $info->{class} . "." . $type;
  $obj->{info}{name}    = "$type:$key";
  $obj->{info}{BoxName} = $dev->{name};

  TO->host_array2($obj->{info}, {host => $host, host_type => $arg->{host_type} || "ib"});

  $obj->{info}{VendorID} = $info->{vendor} || $dev->{vendor} || "?";
  $obj->{info}{NodeWWN}  = $dev->{wwn} if ($dev->{wwn});
  $obj->{info}{LGroup}   = $info->{caption};

  my($report);
  if ($arg->{report}) {   # GET THE REPORT IF AVAILABLE ALREADY
    $report = $arg->{report};
  } else {
    if (!$arg->{wwns}) {  # GET THE WWNS IF NOT THERE ALREADY
       my $rcs = Java::Discovery->deviceSearch({ ip => $dev->{ipno} }, $type);
       $arg = $rcs->[0];
    }
    my(@ports) = split(/,/, $arg->{wwns});  # PARSE WWNS IN THE REPORT.
    my($x);
    for ($x=0; $x <= $#ports; $x++) {
       my $p = $x+1;
       $report->{"fcport.$p.NodeWWN"}      = $dev->{wwn};
       $report->{"fcport.$p._WWN"}         = $ports[$x];
       $report->{"fcport.$p._ElementName"} = $x;
    }
  }

  $obj->{port}= [];
  #
  # ADD PORTS FROM REPORT TO NODE.
  my($x);
  $obj->{info}{port_cnt} = $report->{'fcport.count'};

  for ($x=1; $x <= 20; $x++) {
      last if (!exists  $report->{"fcport.$x._WWN"});

      my $portWWN = lc($report->{"fcport.$x._WWN"});
      my $nodeWWN = lc($report->{"fcport.$x.NodeWWN"});
#      my ($port)  = &_topoPort($portWWN, $nodeWWN);
		my $port = $x;
      $obj->{portInfo}[$port] = {
                 PortWWN => $portWWN,
            LocalPortWWN => $portWWN,
                      Id => $report->{"fcport.$x._Name"} ||
											$report->{"fcport.$x._ElementName"},
                 };
      $to->addSyn($portWWN, "$k:$port");
  }

  bless($obj, uc("TO::$type"));

  $to->addSyn($key, "$type:$key");
  $storages->{"$type:$key"} = $obj;
  
  return $obj;
}


# implementation.xml config topo
sub iconLayout {
  my($this, $obj) = @_;

  my $layout = {};

  my $type = $this->type() || "COMMON";
  my $impl = new Catalog::Implementation($type);
  my $topo = $impl->getFramworkProperty("Topology");
  $layout = $topo->{property}->{Layout}->{property};


  my $rows_of_disk     = $layout->{rows_of_disk} || 1;  # need to be adjusted
  my $disks_per_row    = $layout->{disks_per_row} || 16;
  my $device_type      = $type;
  my $node_type        = "a";     # a for array.
  my $node_color       = $layout->{node_color} || "E0C0D0";
  my $node_gif         = $layout->{node_gif} || "3310.gif"; # taken from htdocs/Topo/TopoGif/
  my $external_ports   = $obj->{info}{port_cnt} || $layout->{external_ports} || 0;

  my ($x, $row_labels, $external_ports_labels);

  for ($x=1; $x <= $external_ports; $x++) {
    $external_ports_labels .= $x;
  }
  for ($x=1; $x <= $rows_of_disk; $x++) {
    $row_labels .= "row$x/";
  }
  chop($row_labels) if ($row_labels);

  my $cat = "$node_type,$device_type,$external_ports/$external_ports_labels,".
         "$disks_per_row,$row_labels,_,,$node_color/$node_gif";

  my $label2 = "Sun 6130";
  my $ses    = 1;

  return ($cat, $label2, $ses);
}

1;
