#!/usr/bin/perl
use Time::Local;
use lib '/home/dave/perl';
use Astro::MoonPhase;
use Astro::Sunrise;
use Astro::Coord::ECI;
use Astro::Coord::ECI::Moon;
use Astro::Coord::ECI::Utils qw{deg2rad};
use Data::Dumper;
require "../cgi-lib.pl";
ReadParse(*params);
print "Content-Type: text/html\n\n";

$days = 30; #Default

if($params{date} =~ /(\d{8})/) {
    $date = $1;
}
if($params{days} =~ /(\d+)/) {
    $days = $1;
}

if($date =~ /(\d\d\d\d)(\d\d)(\d\d)/) {
    my($y,$m,$d) = ($1,$2,$3);
    $starttime = timelocal(0,0,0,$d,$m-1,$y-1900);
} else {
    my(@lt) = localtime(time());
    $starttime = timelocal(0,0,0,$lt[3],$lt[4],$lt[5]);
    $date = sprintf("%04d%02d%02d",$lt[5]+1900,$lt[4]+1,$lt[3]);
}

#Billerica
#my($lat) = deg2rad(42.5583333333333); #42 33'30" N -> 32.55833333333 degrees?
#my($long) = deg2rad(-71.2694444444444); #71 16'10" W -> -71.26944444444 degrees?
#my($alt) = 76 / 1000; #76m above sea level (ish)

#Our House (ish)
my($latd) = 42.542184;
my($longd) = -71.237951;
my($zone) = -5; #-5 hours from GMT

#my($lat) = deg2rad(42.542184);
#my($long) = deg2rad(-71.237951);
my($lat) = deg2rad($latd);
my($long) = deg2rad($longd);
my($alt) = 36 / 1000; #36m above sea level?

my($moon) = Astro::Coord::ECI::Moon->new();

my($time) = $starttime;
my($done) = 0;
my $tdate = $date;

#print "<form style=\"display: inline;\">\n";
#print "</form>\n";

print "<style>\n";
print ".moon \{\n  border: outset 0px;\n  border: 0px;\n  border-spacing: 0px;\n  padding: 0px;\n  margin: 0px;\n\}\n";
print ".moon tr td \{\n  background-color: \#FFFFFF;\n  border-bottom: 1px solid #CCCCCC;\n\}\n";
print ".moon tr th \{\n  background-color: \#000040;\n  border-bottom: 1px solid #CCCCCC;\n  color: \#CCCCCC; \n}\n";
print "<\/style>\n";

print "<table class=\"moon\"><tr>\n";
print "<td></td>\n";
for($h=0;$h<24;$h++) {
    print "<td colspan=6>$h:00</td>";
}
print "</tr>\n";

while(!$done) {
    my($sta) = Astro::Coord::ECI->universal($time)->geodetic($lat,$long,$alt);
    my($ntime,$rflag) = $sta->next_elevation($moon);
    my(@lt) = localtime($ntime);
    my($y,$m,$d) = (sprintf("%04d",$lt[5]+1900),sprintf("%02d",$lt[4]+1),sprintf("%02d",$lt[3]));
    my($ndate) = "$y$m$d";
    if($rflag) {
	$dates{$y}{$m}{$d}{rise} = sprintf("%02d:%02d:%02d",$lt[2],$lt[1],$lt[0]);
	#print "$ndate rise: $dates{$y}{$m}{$d}{rise}\n";
    } else {
	$dates{$y}{$m}{$d}{set} = sprintf("%02d:%02d:%02d",$lt[2],$lt[1],$lt[0]);
	#print "$ndate set: $dates{$y}{$m}{$d}{set}\n";
    }
    if($tdate ne $ndate) {
	#print "Switched from $tdate to $ndate\n";
	my($h,$m);
	if($tdate !~ /(\d\d\d\d)(\d\d)(\d\d)/) {
	    print "WTF? $tdate\n";
	    exit(0);
	}
	($py,$pm,$pd) = ($1,$2,$3);
	my($sunrise,$sunset,$foo) = sunrise($py,$pm,$pd,$longd,$latd,$zone,0);
	my($sun_rt,$sun_st);
	if($sunrise =~ /(\d+):(\d+)/) {
	    $sun_rt = $1 * 3600 + $2 * 60;
	}
	if($sunset =~ /(\d+):(\d+)/) {
	    $sun_st = $1 * 3600 + $2 * 60;
	}

	my($up,$rflag,$sflag,$rh,$rm,$sh,$sm);
	my $rise = $dates{$py}{$pm}{$pd}{rise};
	my $set = $dates{$py}{$pm}{$pd}{set};
	if($rise =~ /(\d\d):(\d\d):(\d\d)/) {
 	    $rt = $3 + $2*60 + $1*60*60;
	} else {
	    $rt = 0;
	}
	if($set =~ /(\d\d):(\d\d):(\d\d)/) {
	    $st = $3 + $2*60 + $1*60*60;
	} else {
	    $st = 59 + 59*60 + 23*60*60;
	}
	print "<tr><th>$py-$pm-$pd</th>\n";
	#print "$tdate:";

	if($rt > $st) { $up = 1; }
	else { $up = 0; }
	for($h=0;$h<24;$h++) {
	    for($m=0;$m<60;$m+=10) {
		my($ht) = $m*60+$h*60*60;
		if($up) {
		    if(!$sflag && $st <= $ht) {
			$up = 0;
			$sflag = 1;
		    }
		} else {
		    if(!$rflag && $rt <= $ht) {
			$up = 1;
			$rflag = 1;
		    }
		}
		my($color,$dist);
		if($ht < ($sun_rt - 60*45) || $ht > ($sun_st + 60*45)) {
		    $color = "#000040";
		} elsif($ht > ($sun_rt + 60*45) && $ht < ($sun_st - 60*45)) {
		    $color = "#80B0FF";
		} else {
		    $dist = ($sun_st - $ht > (60*60*5)) ? ($sun_rt+60*45) - $ht : ($ht - $sun_st+60*45);
		    #dist between 0 and 5400
		    #$color = "#40589F";
		    if($dist < 600)     { $color = "#739EEC"; }
		    elsif($dist < 1200) { $color = "#668DD9"; }
		    elsif($dist < 1800) { $color = "#5A7BC6"; }
		    elsif($dist < 2400) { $color = "#4D6AB3"; }
		    elsif($dist < 3000) { $color = "#40589F"; }
		    elsif($dist < 3600) { $color = "#33468C"; }
		    elsif($dist < 4200) { $color = "#263579"; }
		    elsif($dist < 4800) { $color = "#1A2366"; }
		    elsif($dist <= 5400) { $color = "#0D1253"; }
		    else { $color = "#FFFFFF"; }
		}
		print "<td style=\"width: 12px; background-color: $color;\">";
		if($up) {
		    my(@lt) = (0,$m,$h,$pd,$pm-1,$py-1900);
                    my($t) = timelocal(@lt);
                    my @phase = phase($t);
                    #$char = get_ascii($phase[1]);
                    #print "$char $phase[0]";
		    $img = get_img($phase[1],$phase[0]);
		    my($wax);
		    if($phase[0] < 0.01) { $wax = "New"; }
		    elsif($phase[0] > 0.99) { $wax = "New"; }
		    elsif($phase[0] < 0.49) { $wax = "Waxing"; }
		    elsif($phase[0] > 0.51) { $wax = "Waning"; }
		    else { $wax = "Full"; }
		    
		    print "<img style=\"border: none;\" width=\"12\" height=\"12\" src=\"$img\" title=\"$wax ".sprintf("%.2f",$phase[1]*100)."% full\">";
		} else {
		    print "<img src=\"/~dave/images/spacer.gif\" width=\"12\" height=\"12\">";
		}
		print "</td>";
	    }
	}
	print "</tr>\n";
    }
    $tdate = $ndate;
    $time = $ntime+100;
    #print "Moon ".($rflag ? "rise" : "set")." at ".scalar(localtime($ntime))."\n";
    if(($ntime - $starttime) > ($days*24*60*60)) {
	$done = 1;
    }
}

print "</table>\n";

exit(0);

sub get_img {
    my($full,$phase) = @_;
    my($suffix);
    if($phase < 0.5) { $suffix = 'x'; }
    else { $suffix = 'n'; }
    my($pix) = sprintf("%d",($full * 112));
    if($pix % 2) { $pix++; }
    return "/~dave/images/moon/moon_$pix$suffix.png";
}

sub get_img_old {
    my($full,$phase) = @_;
    my($suffix);
    if($phase < 0.5) { $suffix = 'x'; }
    elsif($phase > 0.5) { $suffix = 'n'; }
    my($pix) = $full * 68;
    if($pix < 6) { $k = '0'; $suffix = ''; }
    elsif($pix < 15) { $k = '1'; }
    elsif($pix < 20) { $k = '2'; }
    elsif($pix < 25) { $k = '3'; }
    elsif($pix < 31) { $k = '4'; }
    elsif($pix < 37) { $k = '5'; }
    elsif($pix < 43) { $k = '6'; }
    elsif($pix < 48) { $k = '7'; }
    elsif($pix < 53) { $k = '8'; }
    elsif($pix < 62) { $k = '9'; }
    else { $k = '10'; $suffix = ''; }
    return "/~dave/images/moon/moon_$k$suffix.GIF";
}

# http://aa.usno.navy.mil/data/docs/RS_OneYear.php
$data = '
       Jan.       Feb.       Mar.       Apr.       May        June       July       Aug.       Sept.      Oct.       Nov.       Dec.  
Day Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set  Rise  Set
     h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m   h m  h m
01  1114 0001  1122 0144  1047 0122  1232 0208  1339 0142  1612 0147  1725 0156  1831 0404  1830 0618  1757 0713  1829 0852  1901 0906
02  1141 0101  1206 0240  1140 0212  1340 0242  1451 0211  1727 0227  1825 0256  1904 0515  1858 0722  1830 0813  1918 0942  2000 0943
03  1211 0200  1257 0333  1240 0257  1450 0314  1605 0242  1839 0315  1916 0403  1934 0623  1926 0824  1907 0911  2011 1026  2100 1016
04  1246 0259  1354 0422  1344 0337  1602 0344  1722 0316  1945 0412  1959 0514  2002 0730  1957 0925  1948 1006  2108 1106  2202 1047
05  1327 0357  1457 0505  1452 0414  1717 0415  1839 0354  2040 0517  2035 0626  2029 0834  2031 1024  2033 1059  2207 1142  2305 1116
06  1415 0452  1605 0544  1603 0447  1834 0448  1954 0440  2127 0627  2106 0736  2057 0937  2109 1121  2124 1146  2309 1215       1144
07  1509 0544  1714 0619  1715 0518  1951 0524  2103 0533  2205 0738  2135 0843  2125 1038  2152 1216  2219 1230       1245  0010 1213
08  1610 0630  1826 0651  1829 0549  2107 0606  2203 0634  2238 0848  2201 0948  2157 1138  2240 1307  2318 1309  0013 1315  0118 1244
09  1715 0712  1938 0721  1944 0620  2218 0654  2252 0740  2306 0955  2228 1050  2232 1236  2333 1353       1344  0119 1344  0228 1319
10  1822 0748  2050 0751  2100 0654  2320 0749  2333 0849  2333 1100  2255 1151  2312 1333       1435  0020 1416  0228 1415  0341 1400
11  1931 0820  2203 0821  2215 0731       0851       0958  2359 1202  2324 1251  2357 1426  0031 1513  0125 1447  0340 1449  0455 1449
12  2041 0850  2317 0854  2327 0813  0014 0956  0007 1104       1302  2357 1350       1516  0133 1548  0232 1517  0454 1528  0606 1546
13  2151 0919       0932       0902  0058 1103  0037 1208  0025 1402       1447  0048 1601  0238 1620  0341 1548  0610 1614  0712 1652
14  2302 0947  0028 1015  0032 0958  0135 1209  0104 1310  0053 1501  0034 1543  0145 1641  0345 1651  0453 1621  0723 1708  0809 1803
15       1018  0136 1105  0129 1059  0206 1313  0130 1411  0123 1559  0116 1635  0246 1718  0454 1721  0607 1658  0832 1810  0856 1917
16  0014 1051  0239 1202  0218 1204  0234 1416  0155 1510  0157 1656  0204 1723  0350 1751  0605 1752  0723 1740  0931 1918  0936 2028
17  0126 1130  0333 1305  0258 1310  0300 1517  0221 1610  0236 1750  0258 1806  0456 1822  0717 1826  0837 1829  1022 2028  1011 2138
18  0237 1215  0419 1411  0333 1415  0326 1617  0250 1708  0320 1841  0356 1845  0603 1852  0831 1904  0946 1925  1104 2138  1041 2244
19  0345 1308  0458 1518  0403 1519  0351 1717  0321 1806  0411 1927  0459 1919  0712 1921  0943 1947  1048 2027  1139 2246  1109 2348
20  0446 1409  0531 1624  0431 1622  0418 1816  0357 1902  0506 2008  0603 1951  0822 1952  1054 2037  1142 2134  1211 2352  1137     
21  0538 1515  0601 1729  0456 1723  0447 1915  0438 1955  0606 2044  0709 2020  0933 2026  1158 2133  1227 2242  1239       1205 0049
22  0623 1624  0628 1832  0522 1824  0520 2012  0524 2044  0708 2117  0815 2049  1044 2104  1256 2236  1305 2349  1306 0055  1235 0150
23  0700 1733  0653 1934  0547 1924  0557 2107  0616 2128  0812 2147  0923 2118  1155 2148  1345 2342  1338       1333 0157  1307 0249
24  0732 1839  0718 2035  0615 2024  0639 2159  0712 2207  0917 2216  1032 2149  1303 2239  1427       1407 0055  1402 0257  1343 0346
25  0800 1944  0745 2135  0645 2122  0727 2246  0812 2242  1023 2244  1142 2223  1405 2338  1503 0049  1435 0159  1432 0357  1424 0442
26  0826 2047  0813 2234  0719 2219  0820 2328  0915 2313  1131 2313  1253 2303  1500       1535 0156  1502 0302  1506 0456  1510 0534
27  0851 2148  0844 2332  0758 2313  0918       1019 2343  1241 2345  1404 2349  1547 0042  1604 0302  1530 0403  1544 0553  1600 0622
28  0916 2248  0919       0842       1019 0006  1125       1353       1511       1628 0149  1632 0406  1559 0504  1626 0647  1655 0706
29  0942 2347  1000 0028  0932 0004  1124 0040  1233 0012  1506 0022  1613 0043  1703 0258  1659 0510  1630 0604  1714 0738  1753 0745
30  1011                  1027 0050  1230 0112  1344 0041  1618 0105  1706 0146  1734 0407  1727 0612  1706 0702  1806 0824  1853 0819
31  1044 0046             1128 0131             1457 0112             1752 0253  1803 0513             1745 0759             1955 0851';

$phases = '1201 N86
1202 N79
1203 N71
1204 N64
1205 N57
1206 N50
1207 N43
1208 N36
1209 N29
1210 N21
1211 N14
1212 N7
1213 X0
1214 X7
1215 X14
1216 X21
1217 X29
1218 X36
1219 X43
1220 X50
1221 X57
1222 X64
1223 X71
1224 X79
1225 X86
1226 X93
1227 N100
1228 N93
1229 N86
1230 N79
1231 N71';

foreach my $line (split /\n/,$phases) {
    if($line =~ /^(\d\d)(\d\d)\s+([XN])(\d+)/) {
	my($month,$day,$wax,$perc) = ($1,$2,$3,$4);
	$phases{$month}{$day}{perc} = $perc;
    }
}

# 0  7 14 21 29 36 43 50 57 64 71 79 86 93 100
#       . .  .   :  :  : o  o  o  O  O  @   @
%phase = (0 => ' ',
	  7 => ' ',
	  14 => '.',
	  21 => '.',
	  29 => '.',
	  36 => ':',
	  43 => ':',
	  50 => ':',
	  57 => 'o',
	  64 => 'o',
	  71 => 'o',
	  79 => 'O',
	  86 => 'O',
	  93 => '@',
	  100 => '@',);


my($year) = 2012;
foreach my $line (split /\n/,$data) {
    next unless($line =~ /^\d+/);
    $line =~ s/^(\d+)//;
    $day = $1;
    my($month) = 1;
    print "Processing $line\n";
    while($line =~ s/^\s\s(\d+|\s{4}) (\d+|\s{4})//) {
	print "Got $1,$2\n";
	my($rise,$set) = ($1,$2);
	if($rise =~ /\d/ || $set =~ /\d/) {
	    if($rise =~ /\d/) {
		$date{$month}{$day}{rise} = $rise;
	    } else {
		$date{$month}{$day}{rise} = '0000';
	    }
	    if($set =~ /\d/) {
		$date{$month}{$day}{set} = $set;
	    } else {
		$date{$month}{$day}{set} = '2359';
	    }
	}
	$month++;
    }
}

foreach my $month (keys %date) {
    foreach my $day (keys %{$date{$month}}) {
	my(@lt) = (0,0,12,$day,$month-1,$year-1900);
	my($t) = timelocal(@lt);
	my @phase = phase($t);
	$phases{$month}{$day}{phase} = $phase[0];
	$phases{$month}{$day}{illum} = $phase[1];
    }
}

for my $month (1..12) {
    foreach my $day (sort {$a <=> $b} (keys %{$date{$month}})) {
	#print "$year-$month-$day: ($date{$month}{$day}{rise}) ($date{$month}{$day}{set})\n";
	my($rise) = $date{$month}{$day}{rise};
	my($set) = $date{$month}{$day}{set};
	my($up) = ($rise > $set) ? 1 : 0;
	print "$year-$month-$day: ";
	#print "$phases{$month}{$day}{phase},$phases{$month}{$day}{illum} ";
	#print "$date{$month}{$day}{rise} $date{$month}{$day}{set} ";
	my($char) = get_ascii($phases{$month}{$day}{illum});
	for(my $h = 0;$h < 24;$h++) {
	    for(my $m = 0;$m < 60; $m+=10) {
		my($cmp) = sprintf("%02d%02d",$h,$m);
		if($up && $set <= $cmp) { $up = 0; $set = 3000; }
		elsif(!$up && $rise <= $cmp) { $up = 1; $rise = 3000; }
		#if($up) { print $phase{$phases{$month}{$day}{perc}}; }
		if($up) {
		    my(@lt) = (0,$m,$h,$day,$month-1,$year-1900);
		    my($t) = timelocal(@lt);
		    my @phase = phase($t);
		    $char = get_ascii($phase[1]);
		    print $char;
		}
		else { print " "; }
	    }
	}
	print "\n";
    }
}

sub get_ascii {
    my($num) = @_;
    my($pts) = char_pts();
    my($int) = int($num*31);
    my(@pchar) = split //,$pts->{$int};
    my $rand = int rand(@pchar);
    return $pchar[$rand];

    if($num < 1/31) { return " "; }
    elsif($num < 2/31) { return "`"; }
    elsif($num < 4/31) { return "'"; }
    elsif($num < 6/31) { return "~"; }
    elsif($num < 8/31) { return ":"; }
    elsif($num < 9/31) { return "}"; }
    elsif($num < 10/31) { return "/"; }
    elsif($num < 11/31) { return "?"; }
    elsif($num < 12/31) { return "="; }
    elsif($num < 13/31) { return "%"; }
    elsif($num < 14/31) { return "7"; }
    elsif($num < 15/31) { return "3"; }
    elsif($num < 16/31) { return "2"; }
    elsif($num < 17/31) { return "\$"; }
    elsif($num < 18/31) { return "Z"; }
    elsif($num < 19/31) { return "5"; }
    elsif($num < 20/31) { return "V"; }
    elsif($num < 21/31) { return "S"; }
    elsif($num < 22/31) { return "8"; }
    elsif($num < 23/31) { return "R"; }
    elsif($num < 24/31) { return "B"; }
    elsif($num < 25/31) { return "@"; }
    elsif($num < 27/31) { return "H"; }
    elsif($num < 28/31) { return "#"; }
    elsif($num < 29/31) { return "N"; }
    else { return "M"; }

    #Courrier New, 10pt, "Default" in PuTTY
    #          1<--
    #`         2
    #          3<--
    #.'        4
    #          5<--
    #,-^!~     6
    #          7<--
    #:_        8
    #;{}       9
    #/\<>|()  10
    #?*       11
    #="       12
    #+%il     13
    #[]17t    14
    #3cjCr    15
    #&2IJoxvz 16
    #$Lu      17
    #6OYZT    18
    #45eGnwsy 19
    #0AfDFVP  20
    #9SUahp   21
    #8Xbdk    22
    #QRq      23
    #WKgBEm   24
    #@        25
    #         26<--
    #H        27
    ##        28
    #N        29
    #M        30
}

sub char_pts {
    my $pts = {
	0 => '    ',
#	1 => '',
	2 => '````',
#       3 => '',
 	4 => ".'.'",
#	5 => '',
	6 => ',-^!~',
#	7 => '',
	8 => ':_:_',
	9 => ';{}',
	10 => "/\\<>|()",
	11 => '?*',
	12 => '="',
	13 => '+%il',
	14 => '[]17t',
	15 => '3cjCr',
	16 => '&2IJoxvz',
	17 => '$Lu',
	18 => '6OYZT',
	19 => '45eGnwsy',
	20 => '0AfDFVP',
	21 => '9SUahp',
	22 => '8Xbdk',
	23 => 'QRq',
	24 => 'WKgBEm',
	25 => '@',
#	26 => '',
	27 => 'H',
	28 => '#',
	29 => 'N',
	30 => 'M',
    };
    for my $n (0..30) {
	if(!length($pts->{$n})) {
	    #$pts->{$n} = $pts->{$n-1};
	    $pts->{$n} = $pts->{$n-1} . $pts->{$n+1};
	}
    }
    return $pts;
}
