#!/usr/bin/perl

# Copyright (C) 2010,2011,2012,2013 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

gpxdump - dump name and coordinates of a GPX or loc file

=head1 SYNOPSIS

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

=head1 DESCRIPTION

gpxdump reads *.gpx or *.loc files and prints the name and
the coordinates of waypoints or geocaches.

=head1 OPTIONS

  --degdec      Print only decimal format
  --degdec1     Print only decimal format with prefix
  --mindec      Print in DDD° MM.MMM format
  --mindec1     Shorter variant
  --mindec2     Print in DDD.MM.MMM format
  --utm         Print in UTM format
  --found       Print all founds with date
  --country     Print country of cache
  --state       Print state of cache
  --dump-config Write arguments as default config and exit
  --version     Print version and exit
  --usage       Print usage
  --man         Display manual page
  -h|-?         Help

=cut

use strict;
use warnings;
use Pod::Usage;
use XML::Twig;
use GEO::Coords;
use Config::IniFiles;

#
# process command line arguments
#
use Getopt::Long;
my $help = 0;
my $man = 0;
my $version = 0;
my $usage = 0;
my $print_degdec = 0;
my $print_degdec1 = 0;
my $print_mindec = 0;
my $print_mindec1 = 0;
my $print_mindec2 = 0;
my $print_dms = 0;
my $print_utm = 0;
my $print_found = 0;
my $print_country = 0;
my $print_state = 0;
my $dump_config = 0;
my $homedir = '';

if ($ENV{HOME}) {
  $homedir = $ENV{HOME};
} elsif ($ENV{HOMEDRIVE} && $ENV{HOMEPATH}) {
  $homedir = $ENV{HOMEDRIVE}."/".$ENV{HOMEPATH};
}
my $cfgname = $homedir."/.geo-tools.cfg";

if (!-r $cfgname) {
  my $cfg = new Config::IniFiles(-default => "Global",
                                 -nocase => 1);
  $cfg->AddSection("gpxdump");
  $cfg->newval("gpxdump", "format", "degdec");
  $cfg->WriteConfig($cfgname);
}

my $cfg = new Config::IniFiles(-file => $cfgname,
                               -default => "Global");
if (!$cfg->SectionExists("gpxdump")) {
  $cfg->AddSection("gpxdump");
  $cfg->newval("gpxdump", "format", "degdec");
  $cfg->WriteConfig($cfgname);
}

my $format = $cfg->val("gpxdump", "format", "degdec");

GetOptions('d|degdec' => \$print_degdec,
           'degdec1' => \$print_degdec1,
           'mindec' => \$print_mindec,
           'mindec1' => \$print_mindec1,
           'm|mindec2' => \$print_mindec2,
           'dms' => \$print_dms,
           'utm' => \$print_utm,
	   'found' => \$print_found,
	   'country' => \$print_country,
	   'state' => \$print_state,
	   'dump-config' => \$dump_config,
	   'version' => \$version,
	   'man' => \$man,
	   'usage' => \$usage,
	   'help|h|?' => \$help) or pod2usage(2);
pod2usage(0) if $help;
pod2usage(-exitstatus => 0, -verbose => 2) if $man;
pod2usage(-exitstatus => 0, -verbose => 0) if $usage;

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

my $argcheck = $print_degdec + $print_degdec1 + $print_mindec +
  $print_mindec1 + $print_mindec2 + $print_dms + $print_utm;

if ($argcheck > 1) {
  pod2usage(-exitstatus => 1, -verbose => 0);
} elsif ($argcheck == 0 && $print_found == 0) {
  if ($format) {
    $print_degdec = 1 if ($format =~ m/degdec/i);
    $print_degdec1 = 1 if ($format =~ m/degdec1/i);
    $print_mindec = 1 if ($format =~ m/mindec/i);
    $print_mindec1 = 1 if ($format =~ m/mindec1/i);
    $print_mindec2 = 1 if ($format =~ m/mindec2/i);
    $print_dms = 1 if ($format =~ m/dms/i);
    $print_utm = 1 if ($format =~ m/utm/i);
  } else {
    $print_degdec = 1;
  }
}

if ($dump_config) {
  $format = "degdec" if ($format =~ m/degdec/i);
  $format = "degdec1" if ($format =~ m/degdec1/i);
  $format = "mindec" if ($format =~ m/mindec/i);
  $format = "mindec1" if ($format =~ m/mindec1/i);
  $format = "mindec2" if ($format =~ m/mindec2/i);
  $format = "dms" if ($format =~ m/dms/i);
  $format = "utm" if ($format =~ m/utm/i);
  WriteConfig();
  exit;
}

my @InputFiles;
if ($#ARGV >= 0) {
  @InputFiles = (@ARGV);
}
else {
  pod2usage(-exitstatus => 1, -verbose => 0);
}

my $Parser =
  new XML::Twig(twig_handlers=>{'gpx/wpt' => \&GPXGetWP,
				'loc/waypoint' => \&LOCGetWP},
		keep_encoding => 1);

foreach my $InputFileName (@InputFiles) {
   $Parser->parsefile($InputFileName);
   $Parser->purge;
}

exit;

sub GPXGetWP
{
 my ($t, $wpt) = @_;
 my $ID = $wpt->first_child_text('name');
 my $desc = $wpt->first_child_text('desc');
 my $cmt = $wpt->first_child_text('cmt');
 my $dec1 = $wpt->{'att'}->{'lat'};
 my $dec2 = $wpt->{'att'}->{'lon'};
 my $cache = $wpt->first_child('groundspeak:cache');

 print "$ID, ";
 print GEO::Coords::sprintf_decdeg($dec1, $dec2, 0) if ($print_degdec);
 print GEO::Coords::sprintf_decdeg($dec1, $dec2, 1) if ($print_degdec1);
 print GEO::Coords::sprintf_mindec($dec1, $dec2, 0) if ($print_mindec);
 print GEO::Coords::sprintf_mindec($dec1, $dec2, 1) if ($print_mindec1);
 print GEO::Coords::sprintf_mindec($dec1, $dec2, 2) if ($print_mindec2);
 print GEO::Coords::sprintf_dms($dec1, $dec2, 0) if ($print_dms);
 print GEO::Coords::sprintf_utm($dec1, $dec2) if ($print_utm);

 if ($print_found) {
   my $logs = $cache->first_child('groundspeak:logs');
   my $log = $logs->first_child('groundspeak:log');
   my $date = substr $log->first_child_text('groundspeak:date'), 0, 10;
   my $finder = $log->first_child_text('groundspeak:finder');
   print ", " if ($argcheck != 0);
   print "$date ($finder)";
 }

 if ($cmt) {
   print ", $cmt";
 }

 if($desc && !$cmt && $cmt ne $desc) {
   if ($cmt) {
     print "; ";
   } else {
     print ", ";
   }
   print "$desc";
 }

 if ($print_country) {
   my $country = $cache->first_child_text('groundspeak:country');
   print ", $country";
 }
 if ($print_state) {
   my $state = $cache->first_child_text('groundspeak:state');
   print ", $state";
 }


 print "\n";

 return;
}

sub LOCGetWP
{
  my ($t, $wpt) = @_;
  my $name = $wpt->first_child('name');
  my $ID = $name->{'att'}->{'id'};
  my $coord = $wpt->first_child('coord');

  print "$ID, ";
  print GEO::Coords::sprintf_mindec($coord->{'att'}->{'lat'},
				    $coord->{'att'}->{'lon'});

  if ($name->text) {
    print ", ", $name->text;
  }

  print "\n";

  return;
}

sub WriteConfig
{
  $cfg->newval("gpxdump", "format", $format);

  $cfg->WriteConfig($cfgname);
}
