#!/usr/local/bin/perl -w

#############################################################################
## Outputs xmgrace .dat file for the input allocation data, which should be
## in the following "events" format:
##
##  <prefix> | <yyyymmdd> | <status> | <rir> | <description>
##
## For example:
##
## 3FFE:0000::/16     | 19981201 | reserved  | IANA      | 6BONE
## 2001:0000::/23     | 19990701 | allocated | IANA      | IANA experimental
## 2001:0200::/23     | 19990701 | allocated | APNIC     | APNIC
##
## Prefixes with a status of "reserved" or "special-use" are ignored.
##
## NOTE: This assumes that the input prefixes do not overlap at all (that is,
##       the input must be the root prefixes in the prefix hierarchy).
##
#############################################################################

use Getopt::Std;
use Date::Calc qw(:all);
use Data::Dumper;
use strict;

my %opts;
unless (getopts("ns", \%opts)) {
  die <<EOF
Usage: $0 -n -s [<events-file>]

where -n = normalize y-axis (only applies with -s),
  and -s = produce stacked plot.
EOF
}

my $normalize_yaxis = defined $opts{'n'};
my $plot_stacked = defined $opts{'s'};

my %dates;
my %org_total;      # org => total allocated over entire period
my %events_by_org;  # <org> => <yyyymmdd> => <size>

while (<>) {
  chomp;
  my ($block, $date, $type, $org, $name) = split /\s*\|\s*/;
  next if $type eq "reserved" || $type eq "special-use";

  $dates{$date} = 1;

  my ($length) = ($block =~ /\/(\d+)/);
  my $size = 2 ** (32 - $length);

  $org_total{$org} += $size;
  $events_by_org{$org}{$date} += $size;
}

my @org_sorted = sort { $org_total{$a} <=> $org_total{$b} } keys %org_total;

if ($plot_stacked) {
  calculate_stacked(\@org_sorted);

  my $i = 0;
  foreach my $org (@org_sorted) {
    print "\@ s$i legend \"$org\"\n";
    ++$i;

    foreach my $date (sort {$a<=>$b} keys %{$events_by_org{$org}}) {
      my $date_frac = date_to_fraction($date);
      my $size = $events_by_org{$org}{$date};
      print "$date_frac $size\n";
    }
  }
}
else {
  my $i = 0;
  foreach my $org (reverse @org_sorted) {
    print "\@ s$i legend \"$org\"\n";
    ++$i;

    my $running_total = 0;
    foreach my $date (sort {$a<=>$b} keys %{$events_by_org{$org}}) {
      my $date_frac = date_to_fraction($date);
      $running_total += $events_by_org{$org}{$date};
      print "$date_frac $running_total\n";
    }
  }
}


#===========================================================================

sub calculate_stacked
{
  my ($org_sorted) = @_;

  my %running_size;
  foreach my $org (@$org_sorted) {
    $running_size{$org} = 0;
  }

  my @org_reverse_sorted = reverse @$org_sorted;

  foreach my $date (sort {$a<=>$b} keys %dates) {
    my $sum = 0;
    foreach my $org (@org_reverse_sorted) {
      $running_size{$org} += ($events_by_org{$org}{$date} || 0);

      $sum += $running_size{$org};
      $events_by_org{$org}{$date} = $sum;
    }
  }
}


#===========================================================================
sub date_to_fraction
{
  my ($yyyymmdd) = @_;

  my ($year, $month, $day) = ($yyyymmdd =~ /^(\d{4})(\d{2})(\d{2})$/);

  my $doy = Day_of_Year($year, $month, $day);
  my $days = Days_in_Year($year, 12);

  return $year + $doy / $days;
}
