#!/usr/bin/perl

# Copyright (C) 2010, 2011 Thorsten Kukuk
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# in Version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301, USA.

=head1 NAME

    spoiler2poi - Create POI file with images from caches

=head1 SYNOPSIS

    spoiler2poi [options] [<gpx-file> ...]

=head1 DESCRIPTION

    spoiler2poi creates a POI file for Garmin GPS devices
    from GPX files and a spoiler directory created by geopics.

=head1 OPTIONS

    -c|--cache=<dir>       Where to find the spoiler2poi cache directory
    -n|--name=<name>       Name of the POI collection
    -o|--poi=<file>        Name of final POI file
    -q|--quiet             Don't inform about manipulating images
    -h|-?|--help	   Help

=head1 INPUT

Input/cache direcotry structure:

 <directory>/<GC-Code>/*.jpg

There can be as many jpeg files in one directory as you wish.

=head1 EXAMPLE

  geopics -d spoiler -p -w -s *.gpx
  spoiler2poi -c spoiler -o POI-Spoiler.gpi *.gpx

*.gpx are the gpx files of the Caches/Pocket Queries with all
the details of the corresponding caches.

=head1 COPYRIGHT

Copyright (c) 2011 by Thorsten Kukuk.  All rights reserved.

This package is free software; you can redistribute it and/or modify
it under the GPL version <http://gnu.org/licenses/gpl2.html>.
There is NO WARRANTY, to the extent permitted by law.

=cut

use strict;
use warnings;
use XML::Twig;
use Pod::Usage;
use File::Path;
use File::Copy;
use GD;

#
# process command line arguments
#
use Getopt::Long;
my $version = 0;
my $help = 0;
my $man = 0;
my $quiet = 0;
my $name = "Geocaching Spoilers";
my $cachedir = "spoiler";
my $poi = "Poi.gpi";
my $tmpdir = "/tmp/POI_Spoiler";

GetOptions('o|poi=s' => \$poi,
	   'c|cache=s' => \$cachedir,
	   'n|name=s' => \$name,
	   'q:1' => \$quiet,
	   'quiet!' => \$quiet,
	   'version' => \$version,
	   'man' => \$man,
	   'help|h|?' => \$help) or pod2usage(2);
pod2usage(0) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;

if ($version) {
  print "spoiler2poi (geo-tools) 1.23\n";
  exit 0;
}

my @InputFiles;
if ($#ARGV >= 0) {
   @InputFiles = (@ARGV);
}
else {
  pod2usage(2);
}

if ($#InputFiles < 0) {
  print "\nNo GPX files specified...\n\n";
  exit 1;
}

my $Parser =
  new XML::Twig(twig_handlers=>{'gpx/wpt/groundspeak:cache' => \&GetCache},
		keep_encoding => 1
	       );

rmtree($tmpdir);
mkpath($tmpdir, {verbose => 0, mode => 0755});

my $OutputFileName = $tmpdir."/POI_Spoiler.gpx";
open (GPXFILE, ">$OutputFileName");

print GPXFILE "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>
<gpx xmlns=\"http://www.topografix.com/GPX/1/1\" creator=\"spoiler2poi by Thorsten Kukuk\" version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX//1/gpx.xsd\">\n\n";

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time());
$year += 1900;
$mon += 1;

print GPXFILE "<metadata>
  <name>$name</name>
  <desc>Spoilerbilder für Geocaching</desc>\n";
printf GPXFILE "  <time>%d-%02d-%02dT%02d:%02d:%02d</time>\n",
  $year, $mon, $mday, $hour, $min, $sec;
print GPXFILE "</metadata>\n\n";

foreach my $InputFileName (@InputFiles) {
   print "Processing input GPX file $InputFileName:\n" unless $quiet;
   $Parser->parsefile($InputFileName);
 }

print GPXFILE "</gpx>\n";
close GPXFILE;

system("gpicreator", "--gpifile", $poi, $OutputFileName);

rmtree($tmpdir);
exit;

sub GetCache
{
  my ($t, $cache) = @_;
  my $wpt = $cache->parent('wpt');
  my $ID = $wpt->first_child_text('name');
  print "Parsing ID: $ID       \r";

  my $cachedir=$cachedir."/".$ID;

  if (-r $cachedir) {
    print "$ID: Found spoilers\n" unless $quiet;

    my $count = 0;
    opendir DIR, $cachedir;
    foreach my $FileName (readdir DIR) {
      if ($FileName =~ m/\.jpg$/i) {
	my($image, $newimage, $width, $height);
	my $newpath = $tmpdir."/Data/".$ID."-".$count;
	mkpath($newpath, {mode => 0755});

	my $srcimage = $cachedir."/".$FileName;
	my $destimage = $newpath."/".$FileName;

	copy($srcimage, $destimage) or die "File cannot be copied.";

	# Rotate image if not in portrait style (to show more details)

	$image = new GD::Image($destimage);
	if (!$image) {
	  print "Warning: format of $destimage\n         cannot be autodetected, trying JPEG\n" unless $quiet;
	  $image = newFromJpeg GD::Image($destimage);
	  printf "ERROR: $destimage couldn't be loaded\n" if (!$image);
	}
	($width,$height) = $image->getBounds();
	if ($width > $height) {
	  $newimage = new GD::Image($height,$width);
	  $newimage = $image->copyRotate90();
	  print "$ID-$count: rotate by 90 degrees\n" unless $quiet;
	  open(PICT,">" . $destimage);
	  binmode(PICT);
	  print PICT $newimage->jpeg(85);
	  close(PICT);
	  undef $image;
	  $image = $newimage;
	}
	($width,$height) = $image->getBounds();
	# 240x400 is the size of the GARMIN display, so
	# bigger images are a waste of space.
	if ($width > 240 || $height > 400) {
	   my $k_w = 240 / $width;
	   my $k_h = 400 / $height;
	   my $k = ($k_h < $k_w ? $k_h : $k_w);
	   my $new_width  = int($width * $k);
	   my $new_height = int($height * $k);

	   $newimage = new GD::Image($new_width, $new_height);
	   $newimage->copyResampled($image,
				    0, 0,               # (destX, destY)
				    0, 0,               # (srcX,  srxY )
				    $new_width, $new_height,  # (destX, destY)
				    $width, $height);

	   print "$ID-$count: resize to $new_width x $new_height\n" unless $quiet;
	   open(PICT,">" . $destimage);
	   binmode(PICT);
	   print PICT $newimage->jpeg(85);
	   close(PICT);
	   undef $image;
	   $image = $newimage;
	 }
	undef $image;

	print GPXFILE "<wpt lat=\"$wpt->{'att'}->{'lat'}\" lon=\"$wpt->{'att'}->{'lon'}\">\n";

        my $desc = $FileName;
        $desc =~ s/\.jpg//i;
	print GPXFILE "  <name>$ID-$desc</name>\n";

	my $name = $cache->first_child_text('groundspeak:name');

	print GPXFILE "  <desc>$desc\n$ID - $name</desc>\n";
	print GPXFILE "  <link href=\"Data/$ID-$count\"/>\n";
	print GPXFILE "</wpt>\n";

	$count++;
      }
    }
    closedir DIR;
  }
}
