#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;
use File::Basename;
use Getopt::Std;
use LWP;

# googlesets.pl - command line interface to the google labs set website
# Author: Dean Wilson
# License: GPL
# Version: 0.2 (20060128)

# grab and validate the arguments
my ($opts, $words) = get_args();

my $url = build_query_string($opts, $words);

my $expanded_set = get_set($url);


if ($opts->{'d'}) { # change the 'for's to maps?
  for my $word (@$words) { print "Param: '$word'\n"; } # DB
  print "GETing: '$url'\n"; # DB
  for my $set_element (@$expanded_set) { print "Expanded Items: '$set_element'\n"; } # DB
} else {
  show_set($expanded_set, $opts);
}


#####################################################################
# --- Subroutines ------------------------------------------------- #
#####################################################################

sub get_args {
  my @words; # these are what base the set on.

  my %opts;
  getopts('dhlms', \%opts); # see usage for full details;

  # look for bad arguments and exit;
  usage() if $opts{'h'}; #request for help
  usage() if ($opts{'s'} && $opts{'l'});

  @words = @ARGV;
  if (scalar @words > 5 || scalar @words < 1) {
    usage();
  }

  return (\%opts, \@words);
}

#-------------------------------------------------------------------#

sub usage {
  my $app = basename($0);

  print<<EOH;

  $app: [-s|-l] [OPTIONS] <word> [additional words]

    -s\tsmall set (default)
    -l\tlarge set
    -m\tmachine suitable output (one line, ':' delimited)
    -h\thelp (this message)

    -s and -l may not be used together.

    $app will try to fetch a google set from the one to five words given.

EOH

  exit 1;
}

#-------------------------------------------------------------------#

sub build_query_string {
  my $opts = shift;
  my $words = shift;

  my $base_url = 'http://labs.google.com/sets?hl=en&';
  my $sets_url; # this gets built and then escaped

  my $offset;
  for my $word (@$words) {
    $offset++;
    $sets_url .= qq{q$offset=$word&};
  }

  # get the set size
  if ($opts->{'l'}) {
    $sets_url .= 'btn=Large Set';
  } else {
    $sets_url .= 'btn=Small+Set+items+or+fewer';
  }

  # encode the query string
  my $q = new CGI($sets_url);
  my $escaped_url = $q->query_string;

  return "$base_url$escaped_url";
}

#-------------------------------------------------------------------#

sub get_set {
  my $url = shift;
  my @expanded_set;

  my $browser = LWP::UserAgent->new();
  my $response = $browser->get($url);

  die "Failed to get the set: ", $response->status_line
    unless $response->is_success;

  my $content = $response->content;

  while($content =~ m!<center>(.*)</center></a></font>!g) {
    push(@expanded_set, $1);
  }

  return \@expanded_set;
}

#-------------------------------------------------------------------#

sub show_set {
  my $expanded_set = shift;
  my $opts = shift;

  if ($opts->{'m'}) {
    local $, = ':';
    print @$expanded_set;
    print "\n";
  } else {
    for my $set_element (@$expanded_set) {
      print "$set_element\n";
    }
  }
}

#-------------------------------------------------------------------#
