#!/usr/bin/perl

####################################################################################################################################
# using:  GoogleMapsKm "A-1234 Dorf, Untere Strasse 142" "A-2345 Stadt, Lange Strasse 4"
# output: 19km,  27min (Untere Strasse 142, 1234 Dorf, Austria -> Lange Strasse 4, 2345 Stadt, Austria)
# defvar: GoogleMapsKm "@LS4=A-2345 Stadt, Lange Strasse 4"
# usevar: GoogleMapsKm "A-1234 Dorf, Untere Strasse 142" "@LS4"
# force:  GoogleMapsKm "A-1234 Dorf, Untere Strasse 142!" "@LS4!"
####################################################################################################################################

my $CACHE=$ENV{HOME}."/.GoogleMapsKm.cache";

use strict;
use warnings;
use Encode qw(from_to);
use JSON;
use DB_File;
use LWP::UserAgent;

my $ua=LWP::UserAgent->new(); $ua->proxy(['http','ftp'], "http://192.168.1.250:8080");

my($all_distance,$all_duration,$last)=(0,0,'');

while($ARGV[0])
{
 my $origin =      $ARGV[0];
 my $destination = $ARGV[1]; shift @ARGV;

 if($origin=~/-l/) { tie(my %cache,"DB_File",$CACHE); print join "\n",map "$_:$cache{$_}",sort keys %cache; untie %cache; exit; }

      $origin=~s/^(\@\w+)=(.+)!?$/defVar($1,$2)/e; last if(!$destination);
      $origin=~s/^(\@\w+)!?$/     getVar($1)/e;
 $destination=~s/^(\@\w+)!?$/     getVar($1)/e;

 my $force=($origin=~s/!$//)+($destination=~s/!$//);

 my($err,$start,$end,$distance,$duration)=getDist($origin,$destination,$force);

 if($err) { printf("!!! %s !!!\n",$err); next }

 $all_distance+=$distance;
 $all_duration+=$duration; $last=$end;

            printf("\n%5.1fkm, %5.1fmin (von %s)",$distance/1000,$duration/60,$start);
}           printf("\n------------------\n"
                    ."%5.1fkm, %5.1fmin (bis %s)\n",$all_distance/1000,$all_duration/60,$last) if($last);

####################################################################################################################################
sub getDist
{
 my($err,$start,$end,$distance,$duration)=(undef,undef,undef,undef,undef);

 tie(my %cache,"DB_File",$CACHE); 

  my($origin,$destination,$force)=@_;            $err="got no origin"       if(!$origin);
                                                 $err="got no destination"  if(!$destination);
  my $cacheVal=$cache{"$origin|$destination"};

  if(!$err && (!defined $cacheVal ||$force))
  {
   my $page='http://maps.googleapis.com/maps/api/directions/json?origin="'.$origin.'"&destination="'.$destination.'"&sensor=false';

   my $response=$ua->get($page);               $err="got no response from $page"       if(!$response);                    sleep(1);
   my $json=$response && $response->content(); $err="got no json data"                 if(!$json);
                                               $err="exeed OVER_QUERY_LIMIT"           if( $json=~/OVER_QUERY_LIMIT/);
   my $data=$json && decode_json $json;        $err="error on $origin => $destination" if(!defined $data->{'routes'}[0]{'legs'}[0]);

   if(!$err)
   {
    $start    = $data->{'routes'}[0]{'legs'}[0]{'start_address'}; from_to($start,"iso-8859-1","utf8");
    $end      = $data->{'routes'}[0]{'legs'}[0]{'end_address'};   from_to($end,  "iso-8859-1","utf8");

    $distance = $data->{'routes'}[0]{'legs'}[0]{'distance'}{'value'};
    $duration = $data->{'routes'}[0]{'legs'}[0]{'duration'}{'value'};

    $cache{"$origin|$destination"}="$start|$end|$distance|$duration"; 
  }}
  elsif($cacheVal)               { ($start,$end,$distance,$duration)=split '\|',$cacheVal; }

 untie %cache;          return $err,$start,$end,$distance,$duration;
}
####################################################################################################################################
sub defVar { my($var,$val)=@_; tie(my %cache,"DB_File",$CACHE); $cache{$var}=$val;     untie %cache; return $val; }
####################################################################################################################################
sub getVar { my($var,$val)=@_; tie(my %cache,"DB_File",$CACHE); $val=$cache{$var}||''; untie %cache; return $val; }
####################################################################################################################################
