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

=for comment

Copyright 2021 Paul C. Leyland

Redistribution and use in source and binary forms, with or without modification, are permitted provided that
the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.

=cut

=for comment

Convert a downloaded HTML-format AAVSO photometry file into three-column space-separated tables suitable for
an APT 'Source List' and for generating BAA-VSS TSV files with APT2VSS. Produce a shell-script for optimized
field solving.

Example: to produce an input file for the variable star AE And, visit https://app.aavso.org/vsp/ and enter "AE
And" in the "WHAT IS THE NAME, DESIGNATION OR AUID OF THE OBJECT?" box, choose the desired chart scale and
select Photometry radio button. You may wish to enter a value into the "MAGNITUDE LIMIT" box and select B and
Rc as additional filters to display. Click the "Plot Chart" button. When photometry table is returned, save
that page in HTML format (in Firefox this is done by right-clicking, choosing "Save page as ..." and "Web
page, HTML only"), choosing AE_And.html as the file name. The resulting HTML file is suitable input for this
script.

=cut

$#ARGV == 0 or die "Usage: $0 photometry_file.html\n";

my ($star_name, $RA_hms, $Dec_hms);			# Star name, RA and Dec
my $sequence;						# AAVSO sequence name
my @headers;						# Table headings
my %comparisons;					# Complete comparison data.
my @comparison_order;					# Original order of comparisons.

sub read_photometry($)	# Read in an AAVSO photometry file and parse information into global variables.
{
    my $phot_file = shift;
    my ($h, $m, $s);
    open (PHOT, $phot_file) or die "Can't read photometry file\n";
    <PHOT> eq "<!DOCTYPE html>\n" or die "$phot_file not in HTML format\n";

    while (<PHOT> ne "<p>Field photometry\n") { };
    ($star_name) = (<PHOT> =~ /^<strong>for (.*)<\/strong>$/);
    while (<PHOT> !~ /includes all comparison stars/) { };
    ($h, $m, $s) = (<PHOT> =~ /(\d+):(\d+):([\d\.\+\-]+)/);
    $RA_hms = "${h}h${m}m${s}s";
    ($h, $m, $s) = (<PHOT> =~ /([\-\d]+):(\d+):([\d\.\+\-]+)/);
    $Dec_hms = "${h}d${m}m${s}s";

    while ($sequence = <PHOT>) {
	last if $sequence =~ s/.*Report this sequence as <strong>(\w+)<\/strong>$/$1/;
    }
    chomp $sequence;

    while (<PHOT> !~ /^\s*<tr>$/) { };			# Move to row of table headers.
    while (<PHOT> =~ /^\s*$|^\s+<th>(.*)<\/th>$/) {
	$1 and push @headers, $1;
    }
    shift @headers;					# Not part of the data, used as a key for %comparisons
    while (<PHOT>) {
	/^\s*$/ and next;
	/<\/tbody>/ and last;
	my @data = ();					# Data for each comparison star
	while (<PHOT>) {
	    /^\s*<\/tr>/ and last;
	    /<td>(.*?)<\/td>/ and push @data, $1;
	}
	my $auid = shift @data;
	push @comparison_order, $auid;
	for (my $i =0; $i <= $#headers; $i++) {
	    $comparisons{$auid}{$headers[$i]} = $data[$i];
	}
    }
    while (my ($comparison, $header) = each %comparisons) {	# Cosmetic tidying of the comparison data.
	while (my ($key, $val) = each %$header) {
	    $val =~ /<strong>(.*?)<\/strong>/ and $val = $1;
	    $val =~ /(.*)<sup>/ and $val = $1;
	    $val =~ s/&mdash;/9.999/;				# Notional magnitude error if not given.
	    $comparisons{$comparison}{$key} = $val;
	}
    }
}

sub write_sources($)
{
    my $file = shift;
    $file =~s/ /_/g;					# Don't like spaces in file names.
    my ($h, $m, $s);

    open (SOURCES_HMS, "> $file") or die "Can't write sources file '$file'\n";
    print SOURCES_HMS "$RA_hms $Dec_hms\n";
    
    foreach (@comparison_order) {
	($h, $m, $s) = ($comparisons{$_}{'RA'} =~ /(\d+):(\d+):([\d\.\+\-]+)/);
	print SOURCES_HMS "${h}h${m}m${s}s ";
	($h, $m, $s) = ($comparisons{$_}{'Dec'} =~ /([\d\+\-]+):(\d+):([\d\.\+\-]+)/);
	print SOURCES_HMS "${h}d${m}m${s}s\n";
    }
    close (SOURCES_HMS);
}

sub write_comparisons($$)
{
    my ($file, $filter) = @_;
    $file =~s/ /_/g;					# Don't like spaces in file names.
    my ($mag, $label, $h, $m, $s);

    open (COMPARISONS_HMS, "> $file") or die "Can't write comparisons file '${file}.cmp'\n";
    print COMPARISONS_HMS "$star_name\n$sequence\n$filter\n";

    foreach (@comparison_order) {
	($h, $m, $s) = ($comparisons{$_}{'RA'} =~ /(\d+):(\d+):([\d\.\+\-]+)/);
	print COMPARISONS_HMS "${h}h${m}m${s}s\t";

	($h, $m, $s) = ($comparisons{$_}{'Dec'} =~ /([\d\+\-]+):(\d+):([\d\.\+\-]+)/);
	print COMPARISONS_HMS "${h}d${m}m${s}s\t";

	$label = $comparisons{$_}{'Label'};
	print COMPARISONS_HMS "$label\t";

	$mag = $comparisons{$_}{$filter};
	print COMPARISONS_HMS "$mag\n";
    }
    close (COMPARISONS_HMS);
}

read_photometry (shift);
$star_name or die "No star name in photometry file\n";

write_sources ("${star_name}.src");

write_comparisons ("${star_name}_B.cmp", 'B');
write_comparisons ("${star_name}_V.cmp", 'V');
write_comparisons ("${star_name}_R.cmp", 'Rc');

chop $RA_hms;  $RA_hms =~ s/[hm]/:/g;
chop $Dec_hms; $Dec_hms =~ s/[dm]/:/g;
open (SOLVE, "> solve-field") or die "Can't write solve-field\n";
print SOLVE "solve-field -O -p -L 0.28 -H 2.4 -u app -8 neg -3 $RA_hms -4 $Dec_hms -5 2.0 -z 2 *.fit\n";
close (SOLVE);

# That's all folks!
