#!/usr/bin/perl

use strict;
use Math::Trig;
use Statistics::Lite;
use SVG;
use Text::CSV;

# Some basic functions first

sub new_earthquake {
    my $eq = {
        id => shift,
        latitude => shift,
        longitude => shift,
        magnitude => shift,
        depth => shift,
        date => shift,
    };
}

sub intensity_plot {
    my ($green_red, $f, $intensity) = @_;
    if ($green_red) {
        if ($f->($intensity) < 256) {
            return (int($f->($intensity)), 0, 255);
        } else {
            return (255, 0, 255 - int($f->($intensity) % 256));
        }
    } else {
        # from (128,128,255) to (128,0,255) to (0,0,128)
        if ($f->($intensity) < 256) {
            return (128, 128 - int($f->($intensity) / 2), 255);
        } else {
            return (0, 0, 255 - int($f->($intensity) % 256 / 2));
        }
    }
}

sub intensity_map_function {
    my ($min, $max, $mode, $x) = @_;
    my $m = 511.0 / (Math::Trig::asinh($max - $mode) 
        - Math::Trig::asinh($min - $mode));
    my $a = -1 * $m * Math::Trig::asinh($min - $mode);
    return ($a + $m * Math::Trig::asinh($x - $mode));
}

# And now the feature presentation

my $eqcsv = Text::CSV->new();
open (EQFILE, "<", 'eqfile') or die $!;
my @earthquakes = ();
my @magnitudes = ();
my @depths = ();
my $head = <EQFILE>;    # off with her head!!
while (my $line = <EQFILE>) {
    if ($eqcsv->parse($line)) {
        my @eq = $eqcsv->fields();
        push @earthquakes, new_earthquake($eq[1], $eq[4], $eq[5], $eq[6], 
            $eq[7], $eq[3]);
        push @magnitudes, $eq[6];
        push @depths, $eq[7];
    } else {
        print "Failed to parse line: " . $eqcsv->error_input;
    }
}
my $mag_function = sub {
    intensity_plot(1, sub {
        (511.0 / Statistics::Lite::range(@magnitudes) * 
            ($_[0] - Statistics::Lite::min)); },
#        intensity_map_function(Statistics::Lite::min(@magnitudes),
#            Statistics::Lite::max(@magnitudes),
#            Statistics::Lite::mode(@magnitudes),
#            $_[0]); },
        $_[0]); };
my $depth_function = sub {
    intensity_plot(0, sub {
        intensity_map_function(Statistics::Lite::min(@depths),
            Statistics::Lite::max(@depths),
            Statistics::Lite::mode(@depths),
            $_[0]); },
        $_[0]); };
# Father forgive me for I have sinned.

my $width = 2700;
my $height = 1350;
my $svg = SVG->new(width => $width, height => $height);
$svg->image(x => 0, y => 0, width => $width, height => $height, 
    '-href' => 'eq-map/earth.png');
foreach my $earthquake (@earthquakes) {
    # Calculate x, y coords:
    my $x = int(($earthquake->{longitude} + 180) / 360.0 * $width);
    my $y = 1350 - int(($earthquake->{latitude} + 90) / 180.0 * $height);
    # Plot magnitude
    my @magcolor = $mag_function->($earthquake->{magnitude});
    $svg->path(d => "M" . ($x - 3) . ",$y A3,3 0 0,1 " . ($x + 3) . 
        ",$y",
        stroke => 'none',
        fill => "rgb(" . join(',',@magcolor) . ")");
    # Plot depth
    my @depcolor = $depth_function->($earthquake->{depth});
    $svg->path(d => "M" . ($x - 3) . ",$y A3,3 0 0,0 " . ($x + 3) .
        ",$y",
        stroke => 'none',
        fill => "rgb(" . join(',',@depcolor) . ")");
}
print $svg->xmlify;
