#!/usr/bin/env perl

# Simple program to look up and print the information on a given address.
#	e.g. "./address_lookup Fairfield Road, Broadstairs, Kent, UK"

use warnings;
use strict;
use autodie qw(:all);

use FindBin qw($Bin);
use lib "$Bin/../lib";
use CHI;
use File::Basename;
use File::Spec;
use Geo::Coder::Bing;
use Geo::Coder::CA;
use Geo::Coder::DataScienceToolkit;
use Geo::Coder::Free;
use Geo::Coder::Free::Local;
use Geo::Coder::GooglePlaces;
use Geo::Coder::List;
use Geo::Coder::OpenCage;
use Geo::Coder::OSM;
use Geo::Coder::Ovi;
use Geo::Coder::Postcodes;
use Geo::Coder::RandMcnally;
use Geo::Coder::US::Census;
use Geo::GeoNames;

if(scalar(@ARGV) == 0) {
	die "Usage: $0 location";
}

my $cachedir;
if(my $e = $ENV{'CACHEDIR'}) {
	$cachedir = File::Spec->catfile($e, basename($0));
} else {
	$cachedir = File::Spec->catfile(File::Spec->tmpdir(), 'cache', basename($0));
}
my $geocoder = Geo::Coder::List->new(cache => CHI->new(driver => 'File', root_dir => $cachedir));
my $freegeocoder;
if(my $oa = $ENV{'OPENADDR_HOME'}) {
	$freegeocoder = Geo::Coder::Free->new(openaddr => $oa);
	# $geocoder->push({ regex => qr/,[\w\s]+,[\w\s]+$/, geocoder => $freegeocoder });
	# US, Canada and Australia are full
	# Counties and towns in the UK are full
	$geocoder->push({ regex => qr/,\s*(USA|US|United States|Canada|Australia)\s*$/, geocoder => $freegeocoder })
		->push({ regex => qr/^([\w\s]+,)?\s*[\w\s]+,\s*[\w\s]+\s*$/, geocoder => $freegeocoder });
} else {
	$freegeocoder = Geo::Coder::Free->new();
	$geocoder->push({ regex => qr/^[\w\s\-]+?,[\w\s]+,[\w\s]+?$/, geocoder => $freegeocoder })
		# E.g. 'Nebraska, USA'
		->push({ regex => qr/^[\w\s]+,\s*(UK|England|Canada|USA|US|United States)$/i, geocoder => $freegeocoder });
}

$geocoder->push({ regex => qr/^[\w\s]+,\s*[\w\s],\s*(UK|England|Wales|Scotland)$/i, geocoder => $freegeocoder })
	->push(Geo::Coder::Free::Local->new());

if(my $username = $ENV{'GEONAMES_USER'}) {
	$geocoder->push(Geo::GeoNames->new(username => $username));
}

# DST isn't that good for the UK
# $geocoder->push({ regex => qr/(UK|United Kingdom|England|USA|US|United States|Wales)$/i, geocoder => Geo::Coder::DataScienceToolkit->new() })
$geocoder->push({ regex => qr/(USA|US|United States)$/i, geocoder => Geo::Coder::DataScienceToolkit->new() })
	->push({ regex => qr/^\d.+?,.+?,\s*(USA|US|United States)$/i, geocoder => Geo::Coder::US::Census->new() })
	->push({ limit => 100, regex => qr/(Canada|USA|United States)$/, geocoder => Geo::Coder::CA->new() })
	->push({ regex => qr/(USA|US|United States)$/i, geocoder => Geo::Coder::RandMcnally->new() })
	->push({ regex => qr/^[\w\s-]+,\s*[\w\s]+,\s*(UK|United Kingdom|England|Wales)$/i, geocoder => Geo::Coder::Postcodes->new() })
	->push(Geo::Coder::OSM->new())
	# ->push({ limit => 200, geocoder => Geo::Coder::XYZ->new()})
	->push(Geo::Coder::Ovi->new());
	# ->push(Geo::Coder::GeocodeFarm->new());	# Needs GT#1 to be fixed

if(my $key = $ENV{'GEO_CODER_OPENCAGE_API_KEY'}) {
	$geocoder->push({ limit => 200, geocoder => Geo::Coder::OpenCage->new(api_key => $key) });
}
if(my $key = $ENV{'GMAP_KEY'}) {
	$geocoder->push({ limit => 200, geocoder => Geo::Coder::GooglePlaces->new(key => $key, api_key => $key) });
}

if(my $key = $ENV{BMAP_KEY}) {
	$geocoder->push(Geo::Coder::Bing->new(key => $key));
}

if((my $ckey = $ENV{'YAHOO_CONSUMER'}) && (my $skey = $ENV{'YAHOO_SECRET'})) {
	$geocoder->push(Geo::Coder::PlaceFinder->new(consumer_key => $ckey, secret_key => $skey));
}

# print join(' ', @ARGV), "\n";
my @locations = $geocoder->geocode(location => join(' ', @ARGV));
print '-' x 40, "\n";
print Data::Dumper->new([\@locations, $geocoder->log()])->Dump();
# print Data::Dumper->new([$geocoder->log()])->Dump();
