#!/usr/bin/perl -l

use lib qw{packages};
use Astro::SpaceElevator 0.05;
use Class::Date qw{date};
use Getopt::Lucid qw{:all};
use SVG::TT::Graph;
use SVG::TT::Graph::TimeSeries;

$Class::Date::DEFAULT_TIMEZONE = 'UTC';

my $opt;

eval
{
    $opt = Getopt::Lucid->getopt([Param("start|s")->required,
                                  Param("end|e")->default("1D"),
                                  Param("interval|i")->default("1h"),
                                  Param("graph|g"),
                                  Switch("lunar|l")]);
};

if ($@)
{
    if (ref $@ eq 'Getopt::Lucid::Exception::ARGV')
    {
        print qq{Error: $@

Usage:
  ./shadows.pl --start "2006-01-01 04:00:00" --end "12h" --interval 5m --graph one-day.svg

Options:
  --start     -s  required  Starting time as a string.
  --end       -e  1 day     Duration of the simulation.
  --interval  -i  1 hour    Size of the time step.
  --graph     -g            Name of a file to write an svg graph to.
  --lunar     -l            When specified, the output will include information
                             on the lunar shadow.

  Note that there are a number of parameters passed to the SVG
  Graphing module that you may want to change, but that currently have
  no command line equivalent. I consider it a bug, but for my purposes
  a fairly minor one. Until I add the necessary options (and some
  smart defaults), you'll want to review the contents of this script
  and make changes as necessary.
};
        exit 1;
    }
    ref $@ ? $@->rethrow : die $@;
}

my $graphname = $opt->get_graph;
my @shadowdata;

my $start = date $opt->get_start;
my $end = $start + $opt->get_end;
my $interval = new Class::Date::Rel $opt->get_interval;

my $include_lunar = $opt->get_lunar;

my $elevator = new Astro::SpaceElevator(0, 120, 100_000, $time);

for (my $current = $start; $current <= $end; $current += $interval)
{
    $elevator->time($current->epoch);
    my $data = $elevator->shadows($include_lunar);
    $data->{time} = $current;

    if ($graphname)
    {
        push @shadowdata, $data;
    }
    else
    {
        local $, = '|';
        local $" = ',';
        print ($current,
               "@{$data->{Earth}{umbra}}",
               "@{$data->{Earth}{penumbra}}",
               "@{$data->{Moon}{umbra}}",
               "@{$data->{Moon}{penumbra}}");
    }
}

if ($graphname)
{
    # You'll probably want to change a number of these values, as
    # they're really only suitable for a particular graph
    my $graph = new SVG::TT::Graph::TimeSeries({height              => 1000,
                                                width               => 1200,
                                                show_data_values    => 0,
                                                key                 => 1,
                                                key_position        => 'bottom',
                                                show_graph_title    => 1,
                                                graph_title         => 'Shadow height on the Space Elevator',
                                                show_x_title        => 1,
                                                x_title             => 'Date',
                                                rotate_x_labels     => 1,
                                                #x_label_format      => '%Y-%m-%d',
                                                x_label_format      => '%H:%M:%S',
                                                #x_label_format      => '%Y-%m-%d %H:%M',
                                                timescale_divisions => '1 hours',
                                                max_scale_value     => 10200,
                                                show_y_title        => 1,
                                                y_title             => 'Height (km)',
                                                style_sheet         => 'graph.css'});
    $graph->max_time_span('30 minutes');

    for $body ('Earth', $include_lunar ? 'Moon' : ())
    {
        for $shadow ('umbra', 'penumbra')
        {
            for $slice (0, 1)
            {
                $graph->add_data({data  => [grep { defined $_->[1] }
                                                 map { [$_->{time},
                                                        $_->{$body}{$shadow}->[$slice]] } @shadowdata],
                                  title => "${body}'s $shadow"});
            }
        }
    }

    open GRAPH, '>', $graphname;
    print GRAPH $graph->burn;
}
