#!/usr/bin/env perl
use warnings;
use strict;

# Animation frames... they are base64 encoded PNGs... I know, ridiculous.
#  But we want the animation to be as nice as possible right?
my $frames = [
q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAOPs
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAbFJJyQAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAD0SURBVCjPfZExasNAEEX3AnuENO5VLSrVuU1lthGoDblB
KhduzDR7ABcuVeYExjeIQTgYppm75P/dlZFCyGs+zNOXtDvuCziQ01vFzaMn36Ey/Va30MZM6Kg+
AMfMW8B47GPcPdXMvu1LK/6hOB4efew8vrYBHDOL0oSWpqIyjd0bqD6qPGInKyXWlJYkU6otoNm+
arI2jlSkqoKJsfUphWmhUGtRGuSA3gvUCVAgLLcGSSpqVc1QjcPxne97W6tzwG1AaRKFugCOmed8
vSrYCo98WWB5KV39waW64qy2WmbRCC925dOavExuhbfJW05n7l9+ALhC6vmFWjsQAAAAAElFTkSu
QmCC
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAOSl
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAKe6grwAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAESSURBVCjPfZGhTsRAEIbXQx8B05CgTm0qa0gN4hRZ0wR7
DoOpAYEhY8ZhNqSyHntpLsFhekkDIRmz78I/u3elJYTPTPJ/M9vprhmG4c0YcxprFg4YZZjzaQ+M
v9XeFi5iS1VN09wjfde6t4i72rnro5p4KOo05f5QMQ81FDbJ8/wC6Z3WpG7oy5UZjaomVlA1FLtS
FipEpVMUAkFVVXWJ/Lxa0wdUF5USVWKNXp3qJCn+UZUQFxhyQmdEj8LGe/+M/Mr7Vjh+SygQc1JH
Wj2wc7LR855u58q3Vm9DNkzCUH3fb5G+aG3j9eK/8CzYsJ+xS48iacGFEg4T8cXMCdJXrcI7nGNw
f9hvCVpjdxizYP7jG3mC6097gdGNAAAAAElFTkSuQmCC
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAN4y
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAJP2l1QAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAADoSURBVCjPZZExCsJAEEX3Ah7BJr3VkjJdWivZJmBrZ21l
YSPTzAFSWOYU4g0UAiJMM3fxz+4qu+QR+JDH30xmnQNPUGbmWfLSzFK9fWb+qROwPPs2RHxn6lRw
9ng9DSHslqodUiv8VQMsN+k8HaAwSVOQ1J4+oVvRvFADFIdOsuqB5Ta3SJWg+gKoKSqjVmqtSZLi
qEaAjmqLUhBaE12E3fjjJsTxW0JKzJUitgOnIAc773qM6g7GUfXhbRtyYBKGuhc84nrxX7gWTFip
dCmSBozKdmm5Yv0zuwosDoM5J2wrrJXaExOtL8p36js7BZOGAAAAAElFTkSuQmCC
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAB1C
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAbj0/bAAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAELSURBVCjPZZGhasRAEIbXt/cINaFwqipExpSYilNlTaD2
XE1NTE/UlDHjasJRGX+2LIG6mhQCpTBQ9l36z24ubMgnMrDfzu7kX2OMuRyG4TOpZ4aUbz+xVj/5
xDipr6ZpnrUe8sIG8lJVk3DIsdzV1t6vVVHHLntWT1mWbbXexPN8DYVJsoSoHujXlhsaV6qGYltK
VNdVVd1q3U1d5D1BVQlQXVDKQu28dnUSFau6a9v2DUa4QJMVuiJ6ETbtjBCHu4Q8MafqHZdDdVb2
et7ro6qjc+4D6q/PNQ3ZMwlDuRnv+hAv/gvPggldQh8fReKAqk6I8kKrsJ8ZzQJhjc7gg/mWYGvY
7ccNgv8H2I/sSNovpXIAAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAFy1
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAApXi9dgAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAADwSURBVCjPZZE9asQwEIV9AR8hTfpUwqW7bVMFNQa3ITdI
tUWaMI0O4MKly5wg5Aa7INgsTDN3yXtjKdj4w3hgPr1BP80FNKDWDZctVysc1S0UMtU7YJf1Grro
hL6qyjmgvQwxvhxVN6yp6OoRsM169nnjfYh9m1dVeXKlCSlNRzVElXvsBeoE2D49229JSTKtylEx
6+JCRbbKRIypL1nJzQRopsksdQiN8oHcQ1GF2VOjJBW1vZpmqGX8fOO819x8A7ZZ54DbgNIkWlTF
/Hq5VeORN+bH/FH6skGHfRRfvnvMfzS1XIwfx+2wzI+1ZegPZM3s4CtHXV4AAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAPGe
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAGyN1JAAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAERSURBVCjPZZEha8RAEIXj2/yEmlCoqloiY8qailNlTCC2
VNfE9ERNWbOuZimRkYWzRyjU1eQgtByM2f/SN7t7d7m7T+zA+5jHJpuN4/idZdllmnPGORufOFd/
KjGJatv2BeGPzI0qKaCqpPYsFeK+Jno4VyViarZEVY7KoihukD7LXIY+tjVVbIPacxuV2VJljpQP
qoaynkVpre+QX+uF+d1tCVFFFsb7knpqTGQ6KI0S2fo0r9i7gnLOvSO/d65jW/a4u7Fs2Ee1o/Oy
1bw9Sd/jkXIdVA/F1jDUMAxrpB8yO1WHG+LXyycPM3z4vU264Fx92fgohxfLLhCvMENTxJ48ONtc
enDwqfJTLj04wvwHlF3r541YQ/UAAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAF7J
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAp/JZbAAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAADwSURBVCjPfZExisMwEEV1AR9hG/euhEt3blMtagxul9wg
VYo0YRodIMWWLnOC4BskYBIC08xd8mcsGyUs+5oP8/yNpHEOXIHlTRJuGa88fGL6VDdfB8M3i9oB
zb3HeOhC+Da1y9jX3dwKfygd988uNMU0qxJoVqY4osXRuXKhkruqLjA9Q0NviiS1KAovqgVlxVHq
MKhSoNoVIdHWmWamTG041ij1dEDvK6kT0Jq1eopMLFCnDFVDf9zq/37e1a/Ha0BxJE7qAjRHe14m
bEWvfMkQW0qTDpirEXeVbJk6c3OOJIV+zdEip5CpEEsn7l9evlnr5WrqxEIAAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFANuU
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAd2wdKwAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAEOSURBVCjPfZGhTgQxEEDr4T4B05CgTjUr15AaxClSswn2
HAazhhMYMmYcpiEn12PJ5hIcZi/ZBEjG9F+Yme5xXUJ4opP0zbTTqTHGnA7D8KZxnyaMMJR8uInx
t9q7KiiuntR727b3EjeOt7smhGtVbcGmanJV+EPpfmpYJVV31toLiUtVN/AV6gWMxhaIalhhqGmm
kj1UQUqQ1bn3/tIu4XNVhU6VMBp/YMW5UtVRVnhUngArLgoEZwAPpOoqxvjEZYR6F0ECRFbxyFYO
7AKt5bzH21LFrZNp0BqBMKvnvu9fJe50vPwu/hbusC/Y5U+h3OBMEaYfRlUvPOUTiYQyOsML9zeH
UyWbl0Uy//ENvvzsX2R5MJUAAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAC6u
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAVagG9QAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAADtSURBVCjPZZExisNADEV9gT1CmvRbDS7dpd1qUWPYNl3q
rVKkCWp0ABcufQqTGyRgCAE1usvqazxLBj8MH/Qseaxp7k7jlHzj/s7DVrbqmVYWqF8HVeQjtRSk
rqjCOXl56om+t6rtcxeF2jsoI895nvWuLKvCZ6gfflH3wctG9a6EOnV1cFBGli4241UVvlqaQoFa
GbomzUqawUF5GEaz1ptIecd80ayCUVniW8rGIpViwcCJ9Ih511MzOzDzbDYmbEOPwiqrKtxivf5f
fi1+wkrlS9F8wABl5E3sn6W+cV+c4m0VrLBWhifSu/4AO9DnffnLtkcAAAAASUVORK5CYII=
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAO6g
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAcA3KOAAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAEQSURBVCjPZZItT8RAEEDXw/0ETEOCQm0qa0gN4hRZ0wR7
DoOp4QSGjBmH2Vwq67Fk0wSH6SVNCMkg5r8ws7s0PfpEJ5m3sx8zNeM4fhhjznNcMi45cmatvmxm
UtW27ZMkPzUebekitspqZm8l3TfO3a1V2aQqF1VRFFeSfdS4T/txI4qjmrmO6h6+XbWBaaUaUegq
ElXX9Y1kLzX+VQEzJDWzLV0flXKitqxVPSWFxnv/Kulb7zvCUoocwQXAM0WVIcB4FgED4lJ1crio
3tFO93t5MCGEdxGHMMBPZ7UbtEMgTCrDYYjtlXfJWOSGYcGQhkLpgsqZZN80EvLMdDpxQm2dkQ/h
v59BlsbVPG2k8b8hhOjwxX93WAAAAABJRU5ErkJggg==
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAG5w
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAAkXIGSwAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAADvSURBVCjPZZExisMwEEVzAR8hjftUwqW7tKkWNQa3YW+Q
KsU2YRodwEVKl3uCkBtkwWQxTDN32f8lJSvjh/GAn/5IHm024AHKmnmU/FhmrX5dZnqpE2A9u8ZH
XEt1Kjg7fB477z/WqulSyr9VDVh3sV8/d76tsFtdkJQGpDSsVedVZt9KVntQ7+x5SCkJplT7Fypm
jR+pSKlMxJj6lsQU1QDgLDQI9fKF3BZq+OcaU70EFbWlGq5QY3/5ZL9jUjfAeneYBpQGUahbgcXx
8qjGXy7M3eKltPmAUXGWKHH54jLfaKi4GC+2W2ATH9aKoT9jaO/jJXUUeQAAAABJRU5ErkJggg==
), q(
iVBORw0KGgoAAAANSUhEUgAAADQAAAAVBAMAAAD7ptBLAAAAAXNSR0IArs4c6QAAACpQTFRFAMll
vf/3//8A/8yZM/8A/5n//5mZ/5kAmZmZAJn//zOZZjP//wAAAAAA4F2XugAAAAF0Uk5TAEDm2GYA
AAAJcEhZcwAACxMAAAsTAQCanBgAAAENSURBVCjPZZEhawMxFMfjt/sIM2EwVRVOnhkxE1XjmYOz
pXrmzCpmRkzcTBiVJwe15SjMzVzhoCs8k++y95Icza0/kT+8H+/xkgghxO0wDN9ZTgw5R5+4VieV
GJP6adv2lXOjSgioilWbsVFU7mqA52tVUhmaM0BVjEG9SCkfOBdhHtoaKrRCyIykzBkqM1M+qJqU
9ZjUvdb6US7M7zJ1MaT0xNJ4X0IHjYmMF6VpCHd9mTfqu4vqyTn3QW1oy452NxYNelLuwtZzV/O+
5nmrmXJbUh0ptAaj+uz7fs95UHXYkJ6er9xn+PC8TVowVwcbP2X6MSrtKG4ow6SIFXPQFjyHDvyv
/FjwHDpC/gFKBu6aA6aScQAAAABJRU5ErkJggg==
)];

use Image::Term256Color;
use MIME::Base64;
use Time::HiRes qw( usleep gettimeofday );
use Getopt::Long;
use Pod::Usage;

my $options = {};
GetOptions( "scale=f" => \$options->{scale_ratio},
            "x_scale=i" => \$options->{scale_x},
            "no_scale" => \$options->{no_scale},
            "loop_times=i" => \$options->{loop_t},
            "run_seconds=i" => \$options->{run_s},
            "utf8" => \$options->{utf8},
            "help" => \$options->{help}
          );

if( $options->{help} ){
  print_usage();
}

my $max_width = `tput cols`;
$max_width = $options->{utf8} ? $max_width : sprintf("%u" , ($max_width / 2));

sub print_usage {
  pod2usage( { -message => $_[0] , -exitval => 1 , -verbose => 0 } );
}

# Scale the animation per options set
{
  my $img_opts;

  if( $options->{scale_ratio} ){
    $img_opts->{scale_ratio} = $options->{scale_r};
  } elsif( $options->{scale_x} ){
    $img_opts->{scale_x} = $options->{scale_x};
  } elsif( $options->{no_scale} ){
    # Do nothing...
  } else {
    $img_opts->{scale_x} = $max_width;
  }

  $img_opts->{utf8} = $options->{utf8};

  my $proc_img = sub {
    my $ascii = Image::Term256Color::convert( decode_base64($frames->[$_[0]]) ,
                                              $img_opts );

    if( !$ascii ){
      print_usage("Error: Invalid image data or file.\n");
    }

    return $ascii . "\n";
  };

  for(0..11){
    $frames->[$_] = $proc_img->($_);
  }
}

# Loop the animation per options set
my $loopcheck;

if( $options->{loop_t} ){
  $loopcheck = sub {
    if( $options->{loop_t} ){
      $options->{loop_t}--;
      return 1;
    } else {
      return 0;
    }
  };
} elsif( $options->{run_s} ){
  my $runtime = gettimeofday();
  $loopcheck = sub {
    if( (scalar(gettimeofday()) - $runtime) < $options->{run_s} ){
      return 1;
    } else {
      return 0;
    }
  };
} else {
  $loopcheck = sub {
    return 1;
  };
}

# Clear the screen
print "\033[2J";

# Animate!
while($loopcheck->()){
  my $frame = 0;
  while($frame < 12){
    print "\033[0;0H"; # Jump to 0,0
    print $frames->[$frame++];
    usleep(70000);
  }
}

exit 0;

__END__

=head1 NAME

nyan - Your very own animated terminal Nyancat!

=head1 SYNOPSIS

nyan [options]

 Options:
   --help|-h            brief help message
   --scale|-s           scale image by the given ratio
   --x_scale|-x         scale image to x 'pixels' wide
   --no_scale|-n        do not scale the image at all
   --loop_times|-l      number of times to loop the animation
   --run_seconds|-r     number of seconds to run the animation
   --utf8|-u            use utf8 half-blocks for pixels

If Nyancat is larger than the current terminal in columns, it will be
automatically scaled to fit unless specified.

If no options are specified, Nyancat will loop forever.

=head1 OPTIONS

=over 8

=item --help|-h

Prints a brief help message and exits.

=item --scale|-s

Scales Nyancat by the provided decimal ratio before
printing.  Superscedes --x_scale.

=item --x_scale|-x

Scales Nyancat width to match the provided integer
in 'pixels'.  Scales the image height proportionally.
Superscedes --no_scale.

=item --no_scale|-n

Disables automatic scaling of Nyancat.

=item --loop_times|-l

Number of times to loop the Nyancat animation.

=item --run_seconds|-r

Number of seconds to run the Nyancat animation.
Note:  This isn't exact.

=item --utf8|-u

Uses utf8 'half-block' characters to effectlivy double the
resolution in the terminal.  May not display properly and
depends on the font used.

=back

=head1 DESCRIPTION

nyan a part of the L<Image::Term256Color> distribution and
includes Nyancat animation frames within the script for enjoyment
on 256 color terminals.

=head1 EXAMPLES

Run it already:

    nyan

=cut