#! /usr/bin/perl -w

use strict;
use warnings;
use utf8;

## IMPORTANT ##
# When Net::Twitter::Lite encounters a Twitter API error or a network error, 
# it throws a Net::Twitter::Lite::Error object. 
# You can catch and process these exceptions by using eval blocks and testing $@
## from http://search.cpan.org/perldoc?Net::Twitter::Lite#ERROR_HANDLING
use Net::Twitter::Lite;
use FindBin qw($Bin);
use YAML::Tiny;
use Data::Dumper;
use Encode;

if (@ARGV < 1) {
    die "usage: $0 screen_name [number_of_pages|all [dump]]\n";
}
my $screen_name = $ARGV[0];
my $pages = $ARGV[1] || 1;
if ($pages eq 'all') {
    $pages = -1;
}
my $dump = $ARGV[2] || 0;

my $conf = loadconf("$Bin/config.yml");
if (! defined $conf) {
    die "$0: cannot parse config file.\n";
}

my $bot = login($conf);
if (! $bot->authorized) {
    die "$0: this client is not yet authorized.\n";
}


eval {
    my $page = 0;
    while ($pages - $page && $page <= 160) {
        $page++;
        my $res = $bot->user_timeline(
            {
                screen_name => $screen_name,
                page        => $page,
            }
        );
        
        if ($dump) {
            foreach my $line (split /\n/, Dumper $res) {
                if ($line =~ /undef/) { next; }
                print $line, "\n";
            }
        }
        else {
            foreach my $status (@{$res}) {
                my $text = "";
                $text .= $status->{user}{name};
                $text .= " [" . $status->{created_at} . "]";
                $text .= " (". $status->{id} . ")";
                $text .= " ". encode('utf8', $status->{text});
                $text =~ s/\n//;
                print $text, "\n";
            }
        }
    }
};
if ($@) {
    evalrescue($@);
}
print "done\n";


sub loadconf {
    # load configration data from yaml formatted file
    #   param   => scalar string of filename
    #   ret     => hash object of yaml data
    
    my $file = shift @_;
    
    my $yaml = YAML::Tiny->read($file);
    
    if ($!) {
        warn "$0: '$file' $!\n";
    }
    
    return $yaml->[0];
}

sub login {
    # make Net::Twitter::Lite object and login
    #   param   => hash object of configration
    #   ret     => Net::Twitter::Lite object
    
    my $conf = shift @_;
    
    my $bot = Net::Twitter::Lite->new(
        consumer_key    => $conf->{consumer_key},
        consumer_secret => $conf->{consumer_secret},
    );
    
    $bot->access_token($conf->{access_token});
    $bot->access_token_secret($conf->{access_token_secret});
    
    return $bot;
}

sub evalrescue {
    # output error message at eval error
    
    use Scalar::Util qw(blessed);
    
    if (blessed $@ && $@->isa('Net::Twitter::Lite::Error')) {
        warn $@->error;
        if ($@->twitter_error) {
            my %twitter_error = %{$@->twitter_error};
            map {
                $twitter_error{"$_ => "} = $twitter_error{$_} . "\n";
                delete $twitter_error{$_}
            } keys %twitter_error;
            warn join("", %twitter_error);
        }
    }
    else {
        warn $@;
    }
}
