#!/usr/bin/perl

#"simpletilev3.1.pl" Script by mentat (mentat@hush.com)
#Uses data from USGS via Microsoft Terraservice
#Copyright 2002-2003 Mentat
#Distribute and modify freely as long as above credit remains
#Requires montage from the ImageMagick package
# and Coordinate.pm by Curtis E. Mills, WE7U ftp://ftp.eskimo.com/u/a/archer/aprs/xastir 

use Coordinate;
use Getopt::Long;

my $maps_path = 'JiGLEMap/maps/';

if(!(GetOptions ('path=s' => \$maps_path))) {
	&usage();
} else {
#	print "Mappack = $mappack\n";
#	print "Path = $path\n";
}

$mappack_array = &mappackSelect();

$mappack = $$mappack_array{'fileName'};

$path = $$mappack_array{'path'};

$type = $$mappack_array{'mapType'};

@ref_x = (1396,697,348,172,86,40,20,10);
@ref_y = (27090,13581,6790,3396,1698,849,424,212);
@ref_utm = (200,400,800,1600,3200,6400,12800,25600);

@ref_x_utm = (279200,278800,278400,275200,275200,256000,256000,256000);
@ref_y_utm = (5418200,5432800,5432800,5435200,5436800,5440000,5440000,5452800);

$zoom = 10;

$maps_path = $path;

($short_name, $long_name, @lat_lons) = &read_mappack("$path/$mappack");

#print "Short_name: $short_name, Long_name: $long_name\n";

if ($type == 1)
{
	$short_name .= "aerial";
	$long_name .= " Aerial";
} elsif ($type == 2)
{
	$short_name .= "topo";
	$long_name .= " Topo";
} else
{
	&usage();
}
	
#print "Short_name: $short_name, Long_name: $long_name\n";

&init_from_lat_lon(@lat_lons);

&get_tiles();

&generate_maps();

&calc_coords();

&write_mappack();

&copy_to_JiGLE();

exit();

sub copy_to_JiGLE() {
	print "Copying to maps to JiGLE: ";
	system("cp $short_name-0.png $short_name-1.png $short_name-2.png $short_name.mappack \"$maps_path/.\"");
	print ".";
	print "\n";
}

sub tile_to_utm() {
#	print "\n\ntile_to_utm...\n-------------\n";
	my $x = shift(@_);
	my $y = shift(@_);
	my $corner = shift(@_);

	if ($x < $ref_x) {
		$diff_x = $ref_x[($zoom % 10)] - $x;
		$x_utm = $ref_x_utm[($zoom % 10)] - ($diff_x * $ref_utm[($zoom %10)]);
	} elsif ($x > $ref_x) {
		$diff_x = $x - $ref_x[($zoom % 10)];
		$x_utm = $ref_x_utm[($zoom % 10)] + ($diff_x * $ref_utm[($zoom %10)]);
	} elsif ($x = $ref_x) {
		$x_utm = $ref_x_utm[($zoom % 10)];
	}

	if ($y < $ref_y) {
		$diff_y = $ref_y[($zoom % 10)] - $y;
		$y_utm = $ref_y_utm[($zoom % 10)] - ($diff_y * $ref_utm[($zoom %10)]);
	} elsif ($y > $ref_y) {
		$diff_y = $y - $ref_y[($zoom % 10)];
		$y_utm = $ref_y_utm[($zoom % 10)] + ($diff_y * $ref_utm[($zoom %10)]);
	} elsif ($y = $ref_y) {
		$y_utm = $ref_y_utm[($zoom % 10)];
	}

	if($corner eq "ul") {
	} elsif ($corner eq "ll") {
		$x_utm += $ref_utm[($zoom % 10)];
	} elsif ($corner eq "ur") {
		$y_utm -= $ref_utm[($zoom % 10)];
	} elsif ($corner eq "lr") {
		$x_utm += $ref_utm[($zoom % 10)];
		$y_utm -= $ref_utm[($zoom % 10)];
	}

	return ($x_utm, $y_utm);
}

sub write_mappack() {
	print "Writing Mappack: ";
	open(MAPPACK,">$short_name.mappack");
	print ".";

	printf MAPPACK ("shortName=$short_name\n");
	print ".";
	printf MAPPACK ("longName=$long_name\n");
	print ".";
	printf MAPPACK ("\n");
	print ".";
	printf MAPPACK ("image.0=JiGLEMap/maps/$short_name-0.png\n");
	print ".";
	printf MAPPACK ("image.1=JiGLEMap/maps/$short_name-1.png\n");
	print ".";
	printf MAPPACK ("image.2=JiGLEMap/maps/$short_name-2.png\n");
	print ".";
	printf MAPPACK ("\n");
	print ".";
	printf MAPPACK ("upperLeftX=%f\n",$UpperLeft->latitude());
	print ".";
	printf MAPPACK ("upperLeftY=%f\n",$UpperLeft->longitude());
	print ".";
	printf MAPPACK ("lowerRightX=%f\n",$LowerRight->latitude());
	print ".";
	printf MAPPACK ("lowerRightY=%f\n",$LowerRight->longitude());
	print ".";

	close(MAPPACK);
	print ".";
	print "\n";
}

sub calc_coords() {
	print "Calculating Coordinates: ";
	@ul = &tile_to_utm($start_i,$start_j, "ul");
	print ".";
	@lr = &tile_to_utm($end_i,$end_j, "lr");
	print ".";

	$UpperLeft = Coordinate->new();

	$UpperLeft->datum("WGS 84");
	$UpperLeft->easting($ul[0]);
	$UpperLeft->northing($ul[1]);
	$UpperLeft->zone($tiles[4]);

	$UpperLeft->utm_to_lat_lon();
	print ".";

	$LowerRight = Coordinate->new();

	$LowerRight->datum("WGS 84");
	$LowerRight->easting($lr[0]);
	$LowerRight->northing($lr[1]);
	$LowerRight->zone($tiles[4]);

	$LowerRight->utm_to_lat_lon();
	print ".";
	print "\n";
}

sub generate_maps() {
	my $x_tiles = ($end_i - $start_i);
	my $y_tiles = ($start_j - $end_j);
#	print "\n\nX: $x_tiles, Y: $y_tiles...\n\n";
	$x_tiles++;
	$y_tiles++;
#	print "\n\nX: $x_tiles, Y: $y_tiles...\n\n";
	$tile_geo = "$x_tiles";
	$tile_geo .= "x";
	$tile_geo .= "$y_tiles";

#	print $tile_geo;

	print "Generating Maps: ";
	$montage = "montage +adjoin +shadow +frame -tile $tile_geo -geometry 200x200+0+0";
	for ($j = $start_j; $j > ($end_j - 1); $j--) {
		for ($i = $start_i; $i < ($end_i + 1); $i++) {
			$montage .= " tilecache/$j.$i.$type.$zone.jpg";
		}
	}
	$montage .= " $short_name-2.png";
#	print "$montage\n";
	system("$montage");

	print ".";

	system("convert -resize 50% $short_name-2.png $short_name-1.png");
	print ".";
	system("convert -resize 25% $short_name-2.png $short_name-0.png");
	print ".";
	print "\n";
}

sub get_tiles() {
	print "Getting tiles: ";
	if (!-d "tilecache")
	{
		system("mkdir tilecache");
	}

	for ($j = $start_j; $j > ($end_j - 1); $j--) {
		for ($i = $start_i; $i < ($end_i + 1); $i++) {
			if (!-e "tilecache/$j.$i.$type.$zone.jpg")
			{
				system("wget -q -O tilecache/$j.$i.$type.$zone.jpg \"http://terraservice.net/tile.ashx?T=$type&S=$zoom&X=$i&Y=$j&Z=$zone\"");
				#print("wget -O $j.$i.jpg \"http://terraservice.net/tile.ashx?T=$type&S=$zoom&X=$i&Y=$j&Z=$zone\"");
				#system("wget -q -O $j.$i.jpg \"http://terraserver.homeadvisor.msn.com/tile.ashx?T=1&S=$zoom&X=$i&Y=$j&Z=$zone\"");
			}
			print ".";
		}
	}
	print "\n";
}

sub lat_lon_to_tile() {
#	print "\n\nlat_lon_to_tile...\n------------------\n";
	my $ul_lat = shift(@_);
	my $ul_lon = shift(@_);
	my $lr_lat = shift(@_);
	my $lr_lon = shift(@_);

	my $UpperLeft = Coordinate->new();
	$UpperLeft->datum("WGS 84");

	$UpperLeft->latitude($ul_lat);
	$UpperLeft->longitude($ul_lon);

	$UpperLeft->lat_lon_to_utm();

#	printf ("UpperLeft Lon: $ul_lon, Lat: $ul_lat, Easting: %f, Northing: %f\n",$UpperLeft->easting(),$UpperLeft->northing());

	@ul_tile = &utm_to_tile($UpperLeft->easting(),$UpperLeft->northing());

	my $LowerRight = Coordinate->new();
	$LowerRight->datum("WGS 84");

	$LowerRight->latitude($lr_lat);
	$LowerRight->longitude($lr_lon);

	$LowerRight->lat_lon_to_utm();

#	printf ("LowerRight Lon: $lr_lon, Lat: $lr_lat, Easting: %f, Northing: %f\n",$LowerRight->easting(),$LowerRight->northing());

	@lr_tile = &utm_to_tile($LowerRight->easting(),$LowerRight->northing());

	my $zone = $UpperLeft->zone();

	return (@ul_tile,@lr_tile,$zone);
}

sub utm_to_tile() {
#	print "\n\nutm_to_tile...\n--------------\n";
	use integer;

	my $easting = shift(@_);
	my $northing = shift(@_);

	$easting = $ref_utm[($zoom % 10)] * ($easting / $ref_utm[($zoom % 10)]);
	$northing = $ref_utm[($zoom % 10)] * ($northing / $ref_utm[($zoom % 10)]);
#	print "ref_x: $ref_x[($zoom % 10)], ref_y: $ref_y[($zoom % 10)]\n";

	if ($easting > $ref_x_utm[($zoom % 10)]) {
#		print "Easting: $easting > $ref_x_utm[($zoom % 10)]\n";
		$easting_tile = ($ref_x[($zoom % 10)] + (($easting - $ref_x_utm[($zoom % 10)]) / $ref_utm[($zoom % 10)]));
#		print "Easting_tile: $easting_tile, Easting: $easting\n";
	} elsif ($easting < $ref_x_utm[($zoom % 10)]) {
#		print "Easting: $easting < $ref_x_utm[($zoom % 10)]\n";
		$easting_tile = ($ref_x[($zoom % 10)] - (($ref_x_utm[($zoom % 10)] - $easting) / $ref_utm[($zoom % 10)]));
#		print "Easting_tile: $easting_tile, Easting: $easting\n";
	} else {
#		print "$easting = $ref_x_utm[($zoom % 10)]\n";
		$easting_tile = $ref_x[($zoom % 10)];
#		print "Easting_tile: $easting_tile, Easting: $easting\n";
	}

	if ($northing > $ref_y_utm[($zoom % 10)]) {
#		print "Northing: $northing > $ref_y_utm[($zoom % 10)]\n";
		$northing_tile = ($ref_y[($zoom % 10)] - (($ref_y_utm[($zoom % 10)] - $northing) / $ref_utm[($zoom % 10)]));
#		print "Northing_tile: $northing_tile, Northing: $northing\n";
	} elsif ($northing < $ref_y_utm[($zoom % 10)]) {
#		print "Northing: $northing < $ref_y_utm[($zoom % 10)]\n";
		$northing_tile = ($ref_y[($zoom % 10)] + (($northing - $ref_y_utm[($zoom % 10)]) / $ref_utm[($zoom % 10)]));
#		print "Northing_tile: $northing_tile, Northing: $northing\n";
	} else {
#		print "$northing = $ref_y_utm[($zoom % 10)]\n";
		$northing_tile = $ref_y[($zoom % 10)];
	}

	return ($easting_tile,$northing_tile);
}

sub exponent() {
	my $number = shift (@_);
	my $power = shift (@_);

	print "$number to the $power power\n";

	my $i;

	for ($i = 0; $i < ($power - 1); $i++) {
		$number *= $number;

	}

	return $number;
}
sub init_from_lat_lon() {
	@tiles = &lat_lon_to_tile(@_);

#	print "UL Tile = $tiles[0],$tiles[1], LR Tile = $tiles[2],$tiles[3], Zone: $tiles[4]\n";
#
#	$x_meters = ($tiles[2] - $tiles[0] + 1) * $ref_utm[($zoom % 10)];
#	$y_meters = ($tiles[1] - $tiles[3] + 1) * $ref_utm[($zoom % 10)];
#
#	print "X meters: $x_meters by Y Meters: $y_meters...\n";


	for (;((($tiles[2] - $tiles[0]) > (5*4)) || (($tiles[1] - $tiles[3]) > (3*4)));) {
		use integer;
		$zoom++;
		print "Zooming... Zoom: $zoom\n";

		@tiles = &lat_lon_to_tile(@_);

#		$x_meters = ($tiles[2] - $tiles[0] + 1) * $ref_utm[($zoom % 10)];
#		$y_meters = ($tiles[1] - $tiles[3] + 1) * $ref_utm[($zoom % 10)];
#
#		print "X meters: $x_meters by Y Meters: $y_meters...\n";
	}

	if (($type == 2) && ($zoom == 10))
	{
		print "Area too small to use topo type.\n";
		exit();
	}

	$start_i = $tiles[0];
	$end_i = $tiles[2];
	$start_j = $tiles[1];
	$end_j = $tiles[3];

#	print "$start_i - $end_i, $start_j - $end_j\n";

	$zone = $tiles[4];

	chop($zone);
}

sub read_mappack() {
	my $mappack_path = shift(@_);

	my $shortName;
	my $longName;
	my $upperLeftX;
	my $upperLeftY;
	my $lowerRightX;
	my $lowerRightY;

	open(MAPPACK,$mappack_path);


	while(<MAPPACK>) {
		if ($_ =~ /shortName.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$shortName = $tmp[1];
#			print "shortName: $shortName\n";
		} elsif ($_ =~ /longName.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$longName = $tmp[1];
#			print "longName: $longName\n";
		} elsif ($_ =~ /upperLeftX.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$upperLeftX = $tmp[1];
#			print "upperLeftX: $upperLeftX\n";
		} elsif ($_ =~ /upperLeftY.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$upperLeftY = $tmp[1];
#			print "upperLeftY: $upperLeftY\n";
		} elsif ($_ =~ /lowerRightX.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$lowerRightX = $tmp[1];
#			print "lowerRightX: $lowerRightX\n";
		} elsif ($_ =~ /lowerRightY.*/) {
			@tmp = split(/=/,$_);
			chomp($tmp[1]);
			$lowerRightY = $tmp[1];
#			print "lowerRightY: $lowerRightY\n";
		}
	}

	close(MAPPACK);

	return ($shortName,$longName,$upperLeftX,$upperLeftY,$lowerRightX,$lowerRightY);
}

sub usage() {
	print "Usage:\n";
	print "\t-path\t\t<path to JiGLE maps directory>\n";
	print "\n";
	exit();
}


sub mappackSelect()
{
	my @maps;

	my $mapCount = 0;

	my $mappackNum;

	my $path = $maps_path;

	my $mapType;

	open(DIRECTORY,"ls -1 $path*.mappack|");

	while(<DIRECTORY>)
	{
		chomp;

		s/$path//;

		if (/aerial/ || /topo/ || /empty/)
		{
			next;
		}

		{
			my %mappack;

			$mappack{'path'} = $path;

			$mappack{'fileName'}  = $_;

			open (MAPPACK,"$path$_");

			while (<MAPPACK>)
			{
				chomp;

				if (/shortName/)
				{
					s/shortName=//;
					$mappack{'shortName'} = "$_";
				}

				if (/longName/)
				{
					s/longName=//;

					$mappack{'longName'} = "$_";
				}
			}

			$maps[$mapCount] = \%mappack;

			$mapCount++;
		}
	}

	close DIRECTORY;

	for ($j = 0; $j < $mapCount; $j++)
	{
		print "$j $maps[$j]{'longName'}\n";
	}

	while (1)
	{
		print "Choose mappack to process: ";

		$mappackNum = <>;

		chomp $mappackNum;

		if (($mappackNum < $mapCount) && ($mappackNum > -1))
		{
			last;
		}

		print "Invalid mappack number. Please try again.\n";
	}

	print "1 Aerial\n2 Topographic\n";

	while (1)
	{
		print "Choose mappack type to generate: ";

		$mapType = <>;

		chomp $mapType;

		if (($mapType < 3) && ($mapType > 0))
		{
			last;
		}

		print "Invalid mappack type. Please try again.\n";
	}

	$maps[$mappackNum]{'mapType'} = $mapType;

	return $maps[$mappackNum];
}
