#!/usr/bin/perl

# Copyright (C) 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

geo-gcinfo - display short info about geocaches

=head1 SYNOPSIS

geo-gcinfo [options] <GCxxx> ...

=head1 DESCRIPTION

Download webpages of caches from geocaching.com and display a
two line summary of that geocache.

=head1 OPTIONS

  -l|--login                Login to retrieve cache information
  --logout                  Logout after download
  -p|--password <password>  Password for geocaching.com
  -u|--user <account>       geocaching.com account
  -q|--quiet                Don't print any status messages
  --dump-config             Write current options as default to config
  --version                 Print version and exit
  --usage                   Print usage
  --man                     Display manual page
  -h|-?                     Help

=cut

use strict;
use warnings;
use Pod::Usage;
use File::Path;
use Config::IniFiles;
use GEO::GC;
use GEO::GCVote;

#
# process command line arguments
#
use Getopt::Long;
my $help = 0;
my $man = 0;
my $version = 0;
my $usage = 0;
my $dump_config = 0;
my $homedir = '';

my %html2utf8 = ('&amp;auml;' => "ä",
                 '&amp;Auml;' => "Ä",
		 '&#246;'     => 'ö',
                 '&amp;ouml;' => "ö",
                 '&amp;Ouml;' => "Ö",
		 '&#252;'     => 'ü',
                 '&amp;uuml;' => "ü",
                 '&amp;Uuml;' => "Ü",
                 '&amp;szlig;' => "ß",
                 '&amp;bdquo;' => "„",
                 '&amp;ldquo;' => "“",
                 '&amp;rdquo;' => "”",
                 '&amp;ndash;' => "–",
                 '&amp;nbsp;' => " "
                );
my $regex = qr/${ \(join'|', map quotemeta, keys %html2utf8)}/;


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("geo-gcinfo");
  $cfg->newval("geo-gcinfo", "save_cookies", 1);
  $cfg->WriteConfig($cfgname);
}

my $cfg = new Config::IniFiles(-file => $cfgname,
                               -default => "Global");
if (!$cfg->SectionExists("geo-gcinfo")) {
  $cfg->AddSection("geo-gcinfo");
  $cfg->newval("geo-gcinfo", "save_cookies", 1);
  $cfg->WriteConfig($cfgname);
}
my $save_cookies = $cfg->val("geo-gcinfo", "save_cookies", 1);
my $sleep = $cfg->val("geo-gcinfo", "sleep", 6);
my $gcuser = $cfg->val("geo-gcinfo", "gcuser");
my $gcpassword = $cfg->val("geo-gcinfo", "gcpassword");
my $quiet = $cfg->val("geo-gcinfo", "quiet");
my $login = $cfg->val("geo-gcinfo", "login", 0);
my $logout = $cfg->val("geo-gcinfo", "logout", 0);
my $gcvote = $cfg->val("geo-gcinfo", "gcvote", 0);

GetOptions('u|user=s' => \$gcuser,
	   'p|password=s' => \$gcpassword,
	   'l:1' => \$login,
	   'login!' => \$login,
	   'logout!' => \$logout,
	   'gcvote!' => \$gcvote,
	   'dump-config' => \$dump_config,
	   'q:1' => \$quiet,
	   'quiet!' => \$quiet,
	   '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 "geo-gcinfo (geo-tools) 1.23\n";
  exit;
}

if ($dump_config) {
  WriteConfig();
  exit 0;
}

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

my $gc;

if ($login) {
  $gc = new GEO::GC(save_cookies => $save_cookies, sleep => $sleep,
		    quiet => $quiet,
		    account => $gcuser, password => $gcpassword);
} else {
  $gc = new GEO::GC(save_cookies => 0, sleep => $sleep,
		    quiet => $quiet, nologin => 1);
}

my $first = 1;

foreach my $GCCODE (@GCCODES) {

  if ($first) {
    $first = 0;
  } else {
    print "-------------------------------------------------------------\n";
  }

  my $content = $gc->webpage($GCCODE, $login);

  if ($content =~ /This cache listing has been archived. Log in to view this page./) {
    print "$GCCODE: Archived\n";
  } else {
    if ($content =~ /<title>\s*GC[0-9a-zA-Z]*\s+(.*)\s+\((.*)\)\s+in\s+(.*)\s+created by\s+(.*)\s*<\/title>/gs) {
      my $name = $1;
      my $type = $2;
      my $location = $3;
      my $owner = $4;
      $name =~ s/($regex)/$html2utf8{$1}/g; $name =~ s/\r|\n//g;
      $type =~ s/\r|\n//g;
      $location =~ s/\r|\n//g;
      $owner =~ s/\r|\n//g;
      $content =~ /a ([A-Za-z][A-Za-z ]+) size geocache, with difficulty of ([0-9\.]+), terrain of ([0-9\.]+)\./;
      my $size = $1;
      my $difficulty = $2;
      my $terrain = $3;
      if ($gcvote) {
	 my $gcvote = new GEO::GCVote ();
	 my ($median, $average) = $gcvote->gcvote($GCCODE);
	 printf "$GCCODE: $name - $type ($size, D$difficulty/T$terrain, GCVote %1.1f)", $average;
      } else {
	print "$GCCODE: $name - $type ($size, D$difficulty/T$terrain)";
      }
      if ($content =~ /This cache has been archived, but is available for viewing for archival purposes./) {
	print " (Archived)\n";
      } elsif ($content =~ /This cache is temporarily unavailable. Read the logs below to read the status for this cache./) {
	print " (Disabled)\n";
      } else {
	print "\n";
      }
      print "Owner: $owner, Location: $location\n";
      if ($login) {
	if ($content =~ /You logged this as Found on (\w*),\s+(\w*)\s+(\d*),\s+(\d*)./gs) {
	  print "Found: $3. $2 $4\n";
	}
      }
    } else {
      print "$GCCODE: Parse Error\n";
    }
  }
}

if ($logout) {
  $gc->random_sleep($gc->sleep);
  $gc->logout();
}

exit;

sub WriteConfig
{
  $cfg->newval("geo-gcinfo", "save_cookies", $save_cookies);
  $cfg->newval("geo-gcinfo", "quiet", $quiet);
  $cfg->newval("geo-gcinfo", "login", $login);
  $cfg->newval("geo-gcinfo", "gcvote", $gcvote);
  $cfg->newval("Global", "gcuser", $gcuser);
  $cfg->newval("Global", "gcpassword", $gcpassword);
  $cfg->newval("Global", "logout", $logout);
  $cfg->newval("Global", "sleep", $sleep);
  $cfg->WriteConfig($cfgname);
}
