#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;

use lib "../../lib";
use HotSaNICparser;
use HotSaNICdiagram;
use RRDs;

# read global settings
#
my $MODNAME=HotSaNICparser::get_module_name();
my %CONFIG=HotSaNICparser::get_config("../..");

my $OUTDIR=$CONFIG{"WEBDIR"}."/".lc $MODNAME;
if ( ! -e $OUTDIR ) { mkdir "$OUTDIR",0755; }

my $IMGFMT=lc $CONFIG{"IMAGEFORMAT"};
my $TEMPNAME="$OUTDIR/temp.$IMGFMT";

my (@ITEMS,$dbfile,$device,$maxin,$maxout,$name,$IOMIN,$range,$descr,$file,$build,$fullrange);
my $SWAPIO=1;
my $SCALE=-1000;
my @FEATURES=();
my $FORCE=@ARGV;

my $COLOR_IN_LINE="00a000";
my $COLOR_IN_AREA="c0ffc0";
my $COLOR_OUT_LINE="c00000";
my $COLOR_OUT_AREA="ffc0c0";
my $COLOR_BORDER="a0a0a0";
my $COLOR_MAXSPEED="ff00ff";
my $COLOR_WRONGDATA="ffffa0";

my $STYLE="bytes";
my $STYLETOTAL="bytes";
my $MULT=1;
my $MULTTOTAL=1;

# read module-specific settings
#
foreach (HotSaNICparser::read_settings(".")) {
  my ($var,$value)=HotSaNICparser::parse_line($_);
  if ($var eq "STYLE") {
    $STYLE=lc $value;
    if ($STYLE eq "bits") { $MULT=8; }
    }
  if ($var eq "STYLETOTAL") {
    $STYLETOTAL=lc $value;
    if ($STYLETOTAL eq "bits") { $MULTTOTAL=8; }
    }
  if ($var eq "SWAPIO") {
    if (index("1 yes true",lc $value) >=0 ) { $SWAPIO=-1; }
    }
  if ($var eq "SCALE") { $SCALE=$value; }
  if ($var eq "DEV") {
    push @ITEMS,$value;
    }
  }

if ($SCALE eq "") { $SCALE=-1000; }
if ($SCALE > 0) { push @FEATURES,"--rigid"; }

my $SWAPOI=-$SWAPIO;

# generate diagrams
#
foreach (@ITEMS) {
  ($device,$maxin,$maxout)=split /,/;
  if (index ($device,"SNMP")>=0) {
    my (undef,$host,$comm,$oid)=split /:/,$device;
    ($name=$host."_".$oid) =~ s/\./_/g;
    $device=$host.":".$oid;
    $dbfile=$host."_".$oid;
    $name =~ s/\//-/g;
    $device =~ s/\//-/g;
    $dbfile =~ s/\//-/g;
    } else {
    if (index ($device,"RRCP")>=0) {
    my (undef,$host,$comm,$port)=split /:/,$device;
    $host =~ s/\./:/g;
    ($name=$host."_".$port) =~ s/\./_/g;
    $name =~ s/:/_/g;
    $device=$host.":p".$port;
    $dbfile=$host."_".$port;
    $dbfile=~ s/\./:/g;
    
    } else { 
    $name=$device; 
    $name =~ s/:/_/g;
    $dbfile=$name;
    $name =~ s/\./_/g;
    }
  }
  # if database exists, create images...
  print "creating images for $device ...\n";
  if ( -e "./rrd/$dbfile.rrd") {
    if ((! defined $maxin) || ($maxin eq "") || ($maxin == 0)) {
      print "  Maximum input speed not set!\n  Please check settings-file!\n  setting speed to 100 MBit\n";
      $maxin=12500000;
      }
    if ((! defined $maxout) || ($maxout eq "") || ($maxout == 0)) {
      print "  Maximum output speed not set!\n  Please check settings-file!\n  setting speed to 100 MBit\n";
      $maxout=12500000;
      }
    $maxin*=$MULT;
    $maxout*=$MULT;
    $IOMIN=abs($SCALE)*$MULT;

    foreach $range ("1h","6h","1day","1week","1month","1year") {
      my ($descr,$file,$build,$fullrange,$DATESTRING)=HotSaNICdiagram::get_diagram_properties($range);
      if ($range eq "1h") { draw_hourly($dbfile,$name,$device,$descr,$file,$DATESTRING,$STYLE,$STYLETOTAL,$MULT,$MULTTOTAL,$IOMIN,$maxin,$maxout,$IMGFMT); }
      else { draw_other($range,$dbfile,$name,$device,$descr,$file,$DATESTRING,$build,$fullrange,$STYLE,$STYLETOTAL,$MULT,$MULTTOTAL,$IOMIN,$maxin,$maxout,$IMGFMT); }
      }

    print "creating weathermap file for $device ...\n";

    &rrd2wmwrite($dbfile,"./rrd/",$OUTDIR);
    
    }
  else { print "  No database $dbfile found\n  Please check if the daemon is running.\n";next; }
  print "\n";
  }
exit 0;

sub draw_hourly {

  my($dbfile,$name,$device,$descr,$file,$DATESTRING,$STYLE,$STYLETOTAL,$MULT,$MULTTOTAL,$IOMIN,$maxin,$maxout,$IMGFMT)=@_;

  my $FILENAME="$OUTDIR/$name-$file.$IMGFMT";

  my $DATE=time;
  
  $MULTTOTAL=3600*$MULTTOTAL;
  
# the scaring ;) definition of "wrong1":
# if TIME < now { if in+out unknown { INF else 0 } else 0 }
#   CDEF:wrong1=TIME,$DATE,LT,maxin,maxout,+,UN,INF,0,IF,0,IF \

  $name =~ s/:/\\:/g;
  $dbfile =~ s/:/\\:/g;
  my ($prints,$xs,$ys)=RRDs::graph $TEMPNAME, "-i", "-b","1024", "-v","$STYLE/s",
    "-s","-3600", "-w",$CONFIG{"WIDTH"}, "-h",$CONFIG{"HEIGHT"}, "-a", uc($IMGFMT),
    "-u",$IOMIN, "-l",(-$IOMIN), "--title", "traffic on $device - last hour ($DATESTRING)",@FEATURES,
    "DEF:dbavgin=rrd/$dbfile.rrd:in:AVERAGE",
    "DEF:dbmaxin=rrd/$dbfile.rrd:in:MAX",
    "DEF:dbavgout=rrd/$dbfile.rrd:out:AVERAGE",
    "DEF:dbmaxout=rrd/$dbfile.rrd:out:MAX",
    "CDEF:avgin=dbavgin,$MULT,*",
    "CDEF:maxin=dbmaxin,$MULT,*",
    "CDEF:totin=dbavgin,$MULTTOTAL,*",
    "CDEF:avgout=dbavgout,$MULT,*",
    "CDEF:maxout=dbmaxout,$MULT,*",
    "CDEF:totout=dbavgout,$MULTTOTAL,*",
    "CDEF:wrong1=TIME,$DATE,LT,maxin,maxout,+,UN,INF,0,IF,0,IF",
    "CDEF:wrong2=0,wrong1,-",
    "CDEF:avgin_draw=avgin,$SWAPIO,*",
    "CDEF:avgout_draw=avgout,$SWAPOI,*",
    "AREA:avgin_draw#d0d0d0:",
    "LINE1:avgin_draw#$COLOR_IN_LINE:input\\g",
    "GPRINT:avgin:AVERAGE:  (avg\\:%7.2lf %s /\\g",
    "GPRINT:maxin:MAX: max\\:%7.2lf %s /\\g",
    "GPRINT:maxin:LAST: current\\:%7.2lf %s $STYLE/s)\\n",
    "AREA:avgout_draw#d0d0d0:",
    "LINE1:avgout_draw#$COLOR_OUT_LINE:output\\g",
    "GPRINT:avgout:AVERAGE: (avg\\:%7.2lf %s /\\g",
    "GPRINT:maxout:MAX: max\\:%7.2lf %s /\\g",
    "GPRINT:maxout:LAST: current\\:%7.2lf %s $STYLE/s)\\n",
    "AREA:wrong1#$COLOR_WRONGDATA:data unknown (device may be down)\\n",
    "AREA:wrong2#$COLOR_WRONGDATA:",
    "HRULE:$maxin#$COLOR_MAXSPEED:Maximum transmission speed without compression (in\\: $maxin / out\\: $maxout $STYLE/s)\\n",
    "HRULE:-$maxout#$COLOR_MAXSPEED",
    "GPRINT:totin:AVERAGE:  totaals for last hour\\:%7.2lf %s $STYLETOTAL input",
    "GPRINT:totout:AVERAGE: / %7.2lf %s $STYLETOTAL output",
    "HRULE:0#000000";

  rename $TEMPNAME,$FILENAME;
  print "  hour    ",$xs,"x",$ys," ",$FILENAME,"\n";
  }

sub draw_other {

  my($range,$dbfile,$name,$device,$descr,$file,$DATESTRING,$build,$fullrange,$STYLE,$STYLETOTAL,$MULT,$MULTTOTAL,$IOMIN,$maxin,$maxout,$IMGFMT)=@_;

  my $FILENAME="$OUTDIR/$name-$file.$IMGFMT";
  
  my $DATE=time;

  $MULTTOTAL=$fullrange*$MULTTOTAL;

  my $make=$FORCE;
  if (! -e "$FILENAME") { $make++; }
  else  {
    my (undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime,undef,undef,undef) = stat( "$FILENAME" );
    if ($DATE > ($mtime+$build)) { $make++; }
    }
  if ($make>0) {
  $name =~ s/:/\\:/g;
  $dbfile =~ s/:/\\:/g;

    my ($prints,$xs,$ys)=RRDs::graph $TEMPNAME, "-i", "-b","1024", "-v","$STYLE/s",
      "-s","-$range", "-w",$CONFIG{"WIDTH"}, "-h",$CONFIG{"HEIGHT"}, "-a", uc($IMGFMT),
      "-u",$IOMIN, "-l",(-$IOMIN), "--title", "traffic on $device - last $descr ($DATESTRING)",@FEATURES,
      "DEF:dbminin=rrd/$dbfile.rrd:in:MIN",
      "DEF:dbmaxin=rrd/$dbfile.rrd:in:MAX",
      "DEF:dbavgin=rrd/$dbfile.rrd:in:AVERAGE",
      "DEF:dbminout=rrd/$dbfile.rrd:out:MIN",
      "DEF:dbmaxout=rrd/$dbfile.rrd:out:MAX",
      "DEF:dbavgout=rrd/$dbfile.rrd:out:AVERAGE",
      "CDEF:minin=dbminin,$MULT,*",
      "CDEF:maxin=dbmaxin,$MULT,*",
      "CDEF:avgin=dbavgin,$MULT,*",
      "CDEF:totin=dbavgin,$MULTTOTAL,*",
      "CDEF:minout=dbminout,$MULT,*",
      "CDEF:maxout=dbmaxout,$MULT,*",
      "CDEF:avgout=dbavgout,$MULT,*",
      "CDEF:totout=dbavgout,$MULTTOTAL,*",
      "CDEF:wrong1=maxin,maxout,+,UN,INF,UNKN,IF",
      "CDEF:wrong2=0,wrong1,-",
      "CDEF:minin_draw=minin,$SWAPIO,*",
      "CDEF:maxin_draw=maxin,$SWAPIO,*",
      "CDEF:avgin_draw=avgin,$SWAPIO,*",
      "CDEF:minout_draw=minout,$SWAPOI,*",
      "CDEF:maxout_draw=maxout,$SWAPOI,*",
      "CDEF:avgout_draw=avgout,$SWAPOI,*",
      "AREA:maxin_draw#$COLOR_IN_AREA:min/max in\\g",
      "LINE1:maxin_draw#$COLOR_BORDER:\\g",
      "AREA:minin_draw#ffffff:\\g",
      "LINE1:minin_draw#$COLOR_BORDER:\\g",
      "GPRINT:minin:MIN:  (%7.2lf %s /\\g",
      "GPRINT:maxin:MAX: %7.2lf %s $STYLE/s)",
      "LINE2:avgin_draw#$COLOR_IN_LINE:avg in\\g",
      "GPRINT:avgin:MIN:  (min\\:%7.2lf %s /\\g",
      "GPRINT:avgin:AVERAGE: avg\\:%7.2lf %s /\\g",
      "GPRINT:avgin:MAX: max\\:%7.2lf %s $STYLE/s)\\n",
      "AREA:maxout_draw#$COLOR_OUT_AREA:min/max out\\g",
      "LINE1:maxout_draw#$COLOR_BORDER:\\g",
      "AREA:minout_draw#ffffff:\\g",
      "LINE1:minout_draw#$COLOR_BORDER:\\g",
      "GPRINT:minout:MIN: (%7.2lf %s /\\g",
      "GPRINT:maxout:MAX: %7.2lf %s $STYLE/s)",
      "LINE2:avgout_draw#$COLOR_OUT_LINE:avg out\\g",
      "GPRINT:avgout:MIN: (min\\:%7.2lf %s /\\g",
      "GPRINT:avgout:AVERAGE: avg\\:%7.2lf %s /\\g",
      "GPRINT:avgout:MAX: max\\:%7.2lf %s $STYLE/s)\\n",
      "AREA:wrong1#$COLOR_WRONGDATA:data unknown (device may be down)\\n",
      "AREA:wrong2#$COLOR_WRONGDATA:",
      "HRULE:$maxin#$COLOR_MAXSPEED:Maximum transmission speed without compression (in\\: $maxin / out\\: $maxout $STYLE/s)",
      "HRULE:-$maxout#$COLOR_MAXSPEED",
      "GPRINT:totin:AVERAGE:  totals for last $descr \\:%7.2lf %s $STYLETOTAL input",
      "GPRINT:totout:AVERAGE: / %7.2lf %s $STYLETOTAL output",
      "HRULE:0#000000";
  
    rename $TEMPNAME,$FILENAME;
    printf "  %-7s %d"."x%d %s\n",$descr,$xs,$ys,$FILENAME;
    }
  }

sub rrd2wmwrite() {

my ($dbname, $logdir, $outdir) = @_;

my $dbnameweb = $dbname;
$dbnameweb =~ s/:/_/g;
$dbnameweb =~ s/\./_/g;
$dbnameweb =~ s/\//-/g;

my $file = $outdir."/".$dbnameweb."_wm.html";


open (WMFILE,">$file");

my $cf = "MAX";

print WMFILE rrd2wm($dbname, $logdir, $cf, "now");
print WMFILE rrd2wm($dbname, $logdir, $cf, "hour");
print WMFILE rrd2wm($dbname, $logdir, $cf, "6h");
print WMFILE rrd2wm($dbname, $logdir, $cf, "day");
print WMFILE rrd2wm($dbname, $logdir, $cf, "week");
print WMFILE rrd2wm($dbname, $logdir, $cf, "month");
print WMFILE rrd2wm($dbname, $logdir, $cf, "year");

$cf = "CURRENT";

print WMFILE rrd2wm($dbname, $logdir, $cf, "now");
print WMFILE rrd2wm($dbname, $logdir, $cf, "hour");
print WMFILE rrd2wm($dbname, $logdir, $cf, "6h");
print WMFILE rrd2wm($dbname, $logdir, $cf, "day");
print WMFILE rrd2wm($dbname, $logdir, $cf, "week");
print WMFILE rrd2wm($dbname, $logdir, $cf, "month");
print WMFILE rrd2wm($dbname, $logdir, $cf, "year");

$cf = "AVERAGE";

print WMFILE rrd2wm($dbname, $logdir, $cf, "now");
print WMFILE rrd2wm($dbname, $logdir, $cf, "hour");
print WMFILE rrd2wm($dbname, $logdir, $cf, "6h");
print WMFILE rrd2wm($dbname, $logdir, $cf, "day");
print WMFILE rrd2wm($dbname, $logdir, $cf, "week");
print WMFILE rrd2wm($dbname, $logdir, $cf, "month");
print WMFILE rrd2wm($dbname, $logdir, $cf, "year");

close(WMFILE);
}


sub rrd2wm() {

my ($dbname, $logdir, $cf, $period) = @_;
my $stepnum = 0;
my $stepsize = 0;

my $cfp = $cf;
if($cf eq "CURRENT") { $cf = "MAX"; };

if ($period eq "now")   { $stepnum = 1 		; $stepsize = 1; };
if ($period eq "hour")  { $stepnum = 6 		; $stepsize = 600; };
if ($period eq "6h")    { $stepnum = 6		; $stepsize = 3600; };
if ($period eq "day")   { $stepnum = 24		; $stepsize = 3600; };
if ($period eq "week")  { $stepnum = (7  * 24)	; $stepsize = 3600; };
if ($period eq "month") { $stepnum = (30 * 24)	; $stepsize = 3600; };
if ($period eq "year")	{ $stepnum = (365* 24)	; $stepsize = 3600; };

my $logfile = "$dbname.rrd";
my $ltime = localtime;
my $time = time;

#this will make sure that we will have a value in case of "now"
$time = int(($time-2)/10) * 10;

my $endtime = int($time/$stepsize) * $stepsize;
my $starttime = $endtime - ($stepsize * ($stepnum - 1));
my ($start,$step,$names,$data) = RRDs::fetch ("$logdir$logfile", "$cf", "-r $stepsize", "-s $starttime", "-e $endtime"); 
my $ERR=RRDs::error;

my $pocetdat = $#$data ;
my $celkem_in = 0;
my $celkem_out = 0;
my $max_in = 0;
my $max_out = 0;
my $val = 0;
if($pocetdat < 0) { 
$pocetdat = 1;

 } else {
$pocetdat += 1;

foreach my $line (@$data) {
  my $lasttime = $start;
  $start += $step;
  my $pozice = 0;
  foreach $val (@$line) {
    $pozice += 1;
    if (!$val) { $val=0; };
      if ($pozice == 1) {
        $celkem_in += $val;
        if ($val > $max_in) {$max_in = $val};
      };
      if ($pozice == 2) {
        $celkem_out += $val;
        if ($val > $max_out) {$max_out = $val};
      };
  }
} #foreach
} #else


$max_in = int($max_in);
$max_out = int($max_out);
my $avg_in = int($celkem_in / $pocetdat);
my $avg_out = int($celkem_out / $pocetdat);
$period = substr($period,0,1);

if($cfp eq "AVERAGE") { return "<!-- avgin $period $avg_in --><!-- avgout $period $avg_out -->\n"; }

if($cfp eq "MAX") { return "<!-- maxin $period $max_in --><!-- maxout $period $max_out -->\n"; }

if($cfp eq "CURRENT") { return "<!-- cuin $period $max_in --><!-- cuout $period $max_out -->\n"; }
} # sub
