#!/usr/bin/perl
my $APP = 'xkcd';
use vars qw($VERSION);
$VERSION = '0.071';

use strict;
use WWW::Mechanize;
use Getopt::Long;
use Pod::Usage;

my $m = WWW::Mechanize->new(
  onwarn  => undef,
  onerror => sub { print "You are doing it Wrong. Stop. Bye.\n" and exit 1; },
);

$m->agent_alias('Linux Mozilla');

my $xkcd_base   = 'http://xkcd.com';
my $xkcd_img    = 'http://imgs.xkcd.com/comics';
my $xkcd_url    = undef;

our($opt_comic_no, $opt_alt) = (-1, 0);
our($opt_download);
our($opt_random);

GetOptions(
  'c|comic:i'   => \$opt_comic_no,
  'a|alt|text'  => \$opt_alt,
  'l|latest'    => sub { $opt_comic_no = -1; },
  'download=s'  => \$opt_download,
  'r|random'    => \$opt_random,

  'h|help'      => sub { pod2usage(verbose => 1); },
  'm|man'       => sub { pod2usage(verbose => 3); },
  'v|version'   => sub { printf("%s v%s\n", $APP, $VERSION) and exit; },
);

$opt_comic_no = $ARGV[0] if $ARGV[0] =~ /^\d+$/;

if($opt_random) {
  $m->get("http://dynamic.xkcd.com/random/comic/");
  ($opt_comic_no) = $m->base =~ m|(\d+)/?$|;
}

$xkcd_url  = "$xkcd_base/$opt_comic_no/";

if($opt_download) {
  download_comic($opt_comic_no, $opt_download);
  exit;
}

if( ($opt_comic_no == -1) and not($opt_alt)) {
  latest($xkcd_base);
}

if($opt_alt) {
  if($opt_comic_no == -1) {
    $xkcd_url = $xkcd_base;
  }
  my(undef, $txt) = fetch($xkcd_url);
  $txt = _format($txt);
  print "\e[1mxkcd # $opt_comic_no\e[m:\n";
  print "$txt\n";
  exit;
}

display_img( fetch($xkcd_url) );


sub latest {
  my $url  = shift;
  $m->get($url) or die($!);

  for($m->content) {
    if($_ =~ m/Permanent.+: (http:.+)</) {
      my $new_url = $1;
      ($opt_comic_no) = $new_url =~ m|(\d+)/?$|;
      display_img( fetch( $new_url ));
      exit;
    }
  }
  return;
}

sub _format {
  my $str = shift;
  $str = join(".\n", split(/(?:\.|!|\?) /, $str));
  $str =~ s/^/ / unless $str =~ /^\s+/;
  return $str;
}

sub download_comic {
  my($comic, $dest) = @_;
  defined $dest or $dest = './';

  $dest .= '/' if $dest !~ m;.*/$;;

  my $url;
  if($comic == -1) {
    $url = $xkcd_base;
  }
  elsif($comic !~ /^\d+$/) {
    print STDERR "'$comic' is not an integer!\n" and exit 1;
  }
  else {
    $url = "$xkcd_base/$comic/";
  }

  my ($img, undef) = fetch($url);
  $m->get($img);

  my($filename) = $img =~ m;.+/(.+\.(?:png|jpg))$;i;
  $filename = "$comic-$filename" unless $comic eq -1;
  $dest .= $filename;

  printf("%s => %s\n",
    $img,
    $dest,
  ) if
  $m->save_content($dest) == 0;
  exit;
}


sub fetch {
  my $url = shift;
  $m->get($url);

  my($img_url, $alt) = (undef) x 2;

  for($m->content) {
    if(m;<img src="($xkcd_img/.+\.(?:png|jpg))" title="(.+)" alt;) {
      $img_url = $1;
      $alt     = $2;
      $alt =~ s/&#39;/'/g;
      last;
    }
  }
  return($img_url, $alt);
}


sub display_img {
  my($url, $text) = @_;

  $text = _format($text);

  $m->get($url);

  if( x() ) {
    system(get_viewer(), $url)  == 0
      and printf("\e[1m%s\e[0m:\n%s\n",
      "xkcd # $opt_comic_no", $text,
    );
    return;
  }

  print "$url\n";
  print "Press any key to continue...\n";

  while(<STDIN>) {
    last;
  }

  printf("%s\n%s\n",
    ($opt_comic_no =~ /^\d+$/)
      ? 'Latest xkcd'
      : "xkcd $opt_comic_no"
    );
}

sub x {
  exists($ENV{DISPLAY}) and return 1;
  return 0;
}

sub get_viewer {
  my $feh = system("which feh &> /dev/null");
  if( ($feh << 8) == 0 ) {
    return('feh', qw(-F -Z -Q -x -B black));
  }
  my $display = system("which display &> /dev/null");
  if( ($display << 8) == 0 ) {
    return('display');
  }

  print STDERR "No viewer available.\n" and exit 1;
}

=pod

=head1 NAME

xkcd - xkcd in your console

=head1 USAGE

xkcd [OPTIONS]

=head1 DESCRIPTION

Command-line interface to xkcd. View, download and enjoy xkcd comics straight
from your shell.

=head1 OPTIONS

  -c,   --comic     comic number
  -l,   --latest    show the latest xkcd comic
  -r,   --random    operate on a random xkcd comic
  -a,   --alt       show the 'mouse over' text
  -d,   --download  download the comic to DESTINATION

  -h,   --help      show the help and exit
  -v,   --version   show version info and exit
  -m,   --man       show the documentation and exit

=head1 PREREQUISITES

To view the xkcd comic in X, B<feh> or B<display> (from the ImageMagick suite)
needs to be installed.

=head1 AUTHOR

  Magnus Woldrich
  CPAN ID: WOLDRICH
  magnus@trapd00r.se
  http://japh.se

=head1 REPORTING BUGS

Report bugs on the issue tracker ( L<https://github.com/trapd00r/xkcd/issues> )
or by mail to <magnus@trapd00r.se>

=head1 COPYRIGHT

Copyright (C) 2010, 2011 Magnus Woldrich. All right reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

=cut
