#! /usr/bin/perl

# (c) 2018 Ervin Peters
# http://coder.ervnet.de
# coder@ervnet.de

use strict;
use warnings;
use diagnostics;

use utf8;

use Math::Trig;
use XML::LibXML::Simple qw(XMLin);

use Encode;
use Term::Encoding qw(term_encoding);
my $encoding = term_encoding;
binmode STDIN,  ":encoding($encoding)";
binmode STDOUT, ":encoding($encoding)";

my $lines = {};

my $fileName = $1 || './20180508-test.gpx';

sub calcDist {
    my ( $self, $other ) = @_;
    my $dlong = $self->{lon} - $other->{lon};
    my $dlat  = $self->{lat} - $other->{lat};
    my $dx = ( 111120 * cos( deg2rad( $self->{lat} + $dlat / 2 ) ) ) * $dlong;
    my $dy = $dlat * 111120;
    return sqrt( $dx * $dx + $dy * $dy );
}

sub checkLine {
    my ( $p1, $p2 ) = @_;
    my $lineKey =
        substr( $p1->{lat}, 0, 10 )
      . substr( $p1->{lon}, 0, 10 )
      . substr( $p2->{lat}, 0, 10 )
      . substr( $p2->{lon}, 0, 10 );
    if ( defined( $lines->{$lineKey} ) ) {

        # segment gibt es schon, hochzählen
        $lines->{$lineKey}->{cnt}++;
    }
    else {

        # entgegengesetzte Richtung
        my $lineKeyR = $p2->{lat} . $p2->{lon} . $p1->{lat} . $p1->{lon};
        if ( defined( $lines->{$lineKeyR} ) ) {

            # segment gibt es schon, hochzählen
            $lines->{$lineKeyR}->{cnt}++;
        }
        else {
            $lines->{$lineKey} = {
                cnt    => 1,
                length => calcDist( $p1, $p2 )
            };
        }
    }
}

my $trkLen = {};

sub checkPoints {
    my ( $points, $trkName ) = @_;

    my $p2;
    foreach my $p1 ( @{$points} ) {
        if ( defined($p2) ) {
            checkLine( $p1, $p2 );
            $trkLen->{$trkName} += calcDist( $p1, $p2 );
        }
        $p2 = $p1;
    }
}

my $gpx = XMLin($fileName);

while ( my ( $key, $val ) = each %{$gpx} ) {

    if ( $key eq 'trk' ) {
        while ( my ( $trkName, $trkData ) = each %{$val} ) {
            $trkLen->{$trkName} = 0;
            while ( my ( $trkDataKey, $trkDataValue ) = each %{$trkData} ) {
                if ( $trkDataKey eq 'trkseg' ) {
                    if ( ref($trkDataValue) eq 'HASH' ) {
                        while ( my ( $segItemKey, $segItemData ) =
                            each %{$trkDataValue} )
                        {
                            if ( $segItemKey eq 'trkpt' ) {
                                checkPoints( $segItemData, $trkName );
                            }
                        }
                    }
                    elsif ( ref($trkDataValue) eq 'ARRAY' ) {
                        foreach my $trkSeg ( @{$trkDataValue} ) {
                            while ( my ( $segItemKey, $segItemData ) =
                                each %{$trkSeg} )
                            {
                                if ( $segItemKey eq 'trkpt' ) {
                                    checkPoints( $segItemData, $trkName );
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

my @len = ( 0, 0, 0, 0, 0, 0 );

while ( my ( $seg, $data ) = each %{$lines} ) {
    $len[ $data->{cnt} ] += $data->{length};
}

while ( my ( $trk, $length ) = each %{$trkLen} ) {
    $length = int($length);
    print "$trk : $length m\n";
}
print "\nBelegung:\n";
for ( my $i = 1 ; $i < 6 ; $i++ ) {
    my $length = int( $len[$i] );
    print "$i-fach belegt : $length m\n" if ( $length > 0 );
}
print "fertig\n";
