#!/usr/bin/perl -w
#
# gpspoint2gpsdrive.pl
#
# Convert gpspoint track file to gpsdrive track file(s)
#
# Copyleft 2002 Stephen Merrony <steveATcygnetDOTcoDOTuk>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Change log:
#
# Author         Version       Details
#---------------------------------------------------------------------------------
# S.Merrony       0.0.2        Fix bogus track extraction, add waypoint extraction
# S.Merrony       0.0.3        Fix case where no altitude, add version number to help

use strict;

my %opts;
use Getopt::Std;
getopts('hf:wv', \%opts);

$opts{h} = 0 if (!defined( $opts{h} ));
$opts{w} = 0 if (!defined( $opts{w} ));
$opts{v} = 0 if (!defined( $opts{v} ));

my $trackfnprefix = "track";
my $trackfnext    = ".sav";
my $pointformat   = "%10.6f %10.6f %10.0d %s\n";  # <=== This is the gpsdrive track format ===
my $wayptfilename = "way.txt";
my $wayptformat   = "%s %10.6f %10.6f\n";      # <=== This is the gpsdrive waypoint format ===

my $wayptcnt      = 0;
my $trackcount    = 0;

# Help!
if ($opts{h} ) {
  my $help = <<'ENDOFHELP';

gpspoint2gpsdrive.pl:
=====================

Extract gpsdrive-compatible track file(s) from a gpspoint file.
Optionally also extracts waypoints and appends them to way.txt.

 -h                     This help message - you guessed that!
 -f <gpspointfilename>  The file to extract tracks from.
 -w                     Extract waypoints and append to way.txt
 -v                     Verbose mode - yada yada yada

Version 0.0.3 (August 2002)

ENDOFHELP
  print $help;
  exit;
}

if (!$opts{f} or $opts{f} eq "" ) {
  print "Error: You must enter a filename via the -f switch.\n";
  exit;
}

use FileHandle;

my $infile;

# open the file for reading if we can - else bail out
$infile = new FileHandle "< $opts{f}";
if (!defined( $infile )) {
  print "Error: Unable to open file '$opts{f}' for input\n";
  exit;
}

my $am_writing = 0;

my ($latitude, $longitude,  $timestamp, $wayptname);
my $altitude = 1.0;
my $thisline;
my $trackfilename;
my $trackfile = new FileHandle;
my $wayptfile = new FileHandle;
my $blocktype;
my $dummytime = 0;

# plough through the file
while (<$infile>) {

  $thisline = $_;
  chomp( $thisline ); # remove newline

  # Gpspoint files contain comments starting with a # symbol, blank lines
  # and lines with comma separated lists of values and name-value pairs
  # We only want certain name-value pairs...

  # ignore comments and blank or very short lines
  if ( (substr( $thisline, 0, 1 ) ne "#") &&
       (length( $thisline ) > 5 ) ) {
    
    my (@pairs, $pair);

    @pairs = split( ' ', $thisline );
    foreach $pair ( @pairs ) {
      my $name = "";
      my $value = "";
      ($name, $value) = split( '=', $pair );
      if (defined( $name ) && defined( $value )) { # only process pairs
	$value = substr( $value, 1, length( $value ) - 2 );  # remove quotes

	# starting a new track?
	if (($name eq "type") && ($value eq "track" )) {
	  # $trackfile->close if ($am_writing);
	  $am_writing = 0;
	  $blocktype = "TRACK";
	  print "Info: Found start of track\n" if ($opts{v} eq 1);
	}
	# new set of waypoints?
	elsif (($name eq "type") && ($value eq "waypointlist") && $opts{w}) {
	  $am_writing = 0;
	  $blocktype = "WAYPOINTS";
	  print "Info: Found start of waypoint list\n" if ($opts{v} eq 1);
	  if (!$wayptfile->open( ">> $wayptfilename" )) {
	    print "Error: Unable to append to waypoint file '$wayptfilename'\n";
	    exit;
	  }
	  $am_writing = 1;
	  print "Info: Starting writing waypoint s to '$wayptfilename'\n" if ($opts{v} eq 1);
	}
	elsif (($name eq "type") && ($value eq "route")) {
	  # not interested in routes at this stage
	  $blocktype = "";
	  $am_writing = 0;
	}
     
	# trap other info types here?

	# name of a new track
	if (defined( $name ) && ($name eq "name") && defined( $blocktype ) && ($blocktype eq "TRACK")) {
	  $trackfilename = $trackfnprefix . $value . $trackfnext;
	  if (!$trackfile->open("> $trackfilename" )) {
	    print "Error: Unable to open track output file '$trackfilename'\n";
	    exit;
	  }
	  $am_writing = 1;
	  $trackcount++;
	  print "Info: Starting to write track '$trackfilename'\n" if ($opts{v} eq 1);
	}

	# name of a new waypoint
	if (($opts{w} eq 1) && ($blocktype eq "WAYPOINTS") && ($name eq "name")) {
	  $wayptname = $value;
	  $wayptcnt++;
	}

	if ($name eq "latitude" ) {
	  $latitude  = $value;
	}
	if ($name eq "longitude" ) {
	  $longitude = $value;
	}
	if ($name eq "altitude" ) {
	  $altitude  = $value;
	}
	if ($name eq "unixtime" ) {
	  $timestamp = localtime( $value );
	}
      }
	
    } # end of name-value pair loop
    #print $thisline;
  } #end if

  # done with this line - write out a trackfile line if we have one
  if ($am_writing && defined( $longitude )  && ($blocktype eq "TRACK")) {
    # some tracks have no time info - so we'll insert an early timestamp
    $timestamp = localtime(0) if (!defined( $timestamp ));
    printf $trackfile $pointformat, ($latitude, $longitude, $altitude, $timestamp);
  }

  # done with this line - write out a waypoint line if we have one
  if ($am_writing && defined( $latitude )  && ($blocktype eq "WAYPOINTS")) {
    printf $wayptfile $wayptformat, ($wayptname, $latitude, $longitude);
  }

} # end of per-line loop
 
# clean up nicely
$infile->close;
$trackfile->close if ($opts{w} eq 1);

print "Info: All done.\n" if ($opts{v} eq 1);
print "$trackcount tracks and $wayptcnt waypoints extracted\n";
