#!/usr/bin/perl -w

use strict;

use Graphics::Framebuffer;
use List::Util qw(min max);

system('clear');
$| = 1;

my $file = 0;
my $arg  = join('', @ARGV);
my $new_x;
my $new_y;
my $F;
my $dev = 0;

$file = 1 if ($arg =~ /file/i);    # File Handle drawing mode
if ($arg =~ /(\d+)/) {
    $dev = $1;
}

if ($arg =~ /X(\d+)/) {
    $new_x = $1;
}
if ($arg =~ /Y(\d+)/) {
    $new_y = $1;
}

if (defined($new_x)) {
    $F = Graphics::Framebuffer->new('FB_DEVICE' => "/dev/fb$dev",'FILE_MODE' => $file, 'SHOW_ERRORS' => 1, 'SIMULATED_X' => $new_x,'SIMULATED_Y' => $new_y);
} else {
    $F = Graphics::Framebuffer->new('FB_DEVICE' => "/dev/fb$dev",'FILE_MODE' => $file, 'SHOW_ERRORS' => 1);
}

$SIG{'QUIT'} = sub {$F->clip_reset();$F->cls('ON'); exit(0);};
$SIG{'INT'}  = sub {$F->clip_reset();$F->cls('ON'); exit(0);};

my $screen_width  = $F->{'XRES'};
my $screen_height = $F->{'YRES'};
my $xm            = $F->{'XRES'} / 1920;
my $ym            = $F->{'YRES'} / 1080;
my $XX            = $screen_width;
my $YY            = $screen_height;
my $center_x      = $XX / 2;
my $center_y      = $YY / 2;
my $factor        = 5;

$F->cls('OFF');
print_it($F, 'Plotting Test');
my $s = time + $factor;
while (time < $s) {
    my $x = int(rand($screen_width));
    my $y = int(rand($screen_height));
    $F->set_color({'alpha' => 255, 'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->plot({'x' => $x, 'y' => $y});
} ## end while (time < $s)

print_it($F, 'Line Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->line({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY)});
} ## end for (my $l = $F->{'Y_CLIP'...})

print_it($F, 'Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY)});
}

print_it($F, 'Filled Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'filled' => 1});
}

print_it($F, 'Vertical Gradient Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xx'       => rand($XX),
            'yy'       => rand($YY),
            'filled'   => 1,
            'gradient' => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)
print_it($F, 'Horizontal Gradient Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xx'       => rand($XX),
            'yy'       => rand($YY),
            'filled'   => 1,
            'gradient' => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'radius' => rand($XX / 16)});
}

print_it($F, 'Filled Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box({'x' => rand($XX), 'y' => rand($YY), 'xx' => rand($XX), 'yy' => rand($YY), 'radius' => rand($XX / 16), 'filled' => 1});
}

print_it($F, 'Vertical Gradient Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xx'       => rand($XX),
            'yy'       => rand($YY),
            'radius'   => rand($XX / 16),
            'filled'   => 1,
            'gradient' => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Horizontal Gradient Rounded Box Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->box(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xx'       => rand($XX),
            'yy'       => rand($YY),
            'radius'   => rand($XX / 16),
            'filled'   => 1,
            'gradient' => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y)});
}

print_it($F, 'Filled Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y), 'filled' => 1});
}

print_it($F, 'Vertical Gradient Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'radius'   => rand($center_y),
            'filled'   => 1,
            'gradient' => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Horizontal Gradient Circle Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'radius'   => rand($center_y),
            'filled'   => 1,
            'gradient' => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Arc Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->arc({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y), 'start_degrees' => rand(360), 'end_degrees' => rand(360)});
}

print_it($F, 'Poly Arc Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->poly_arc({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y), 'start_degrees' => rand(360), 'end_degrees' => rand(360)});
}

print_it($F, 'Filled Pie Test');
$s = time + ($factor * 2);
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->filled_pie({'x' => rand($XX), 'y' => rand($YY), 'radius' => rand($center_y), 'start_degrees' => rand(360), 'end_degrees' => rand(360)});
}

print_it($F, 'Vertical Gradient Filled Pie Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->filled_pie(
        {
            'x'             => rand($XX),
            'y'             => rand($YY),
            'radius'        => rand($center_y),
            'start_degrees' => rand(360),
            'end_degrees'   => rand(360),
            'gradient'      => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Horizontal Gradient Filled Pie Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->filled_pie(
        {
            'x'             => rand($XX),
            'y'             => rand($YY),
            'radius'        => rand($center_y),
            'start_degrees' => rand(360),
            'end_degrees'   => rand(360),
            'gradient'      => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse({'x' => rand($XX), 'y' => rand($YY), 'xradius' => rand($center_x), 'yradius' => rand($center_y)});
}

print_it($F, 'Filled Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse({'x' => rand($XX), 'y' => rand($YY), 'xradius' => rand($center_x), 'yradius' => rand($center_y), 'filled' => 1});
}

print_it($F, 'Vertical Gradient Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xradius'  => rand($center_x),
            'yradius'  => rand($center_y),
            'filled'   => 1,
            'gradient' => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Horizontal Gradient Ellipse Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->ellipse(
        {
            'x'        => rand($XX),
            'y'        => rand($YY),
            'xradius'  => rand($center_x),
            'yradius'  => rand($center_y),
            'filled'   => 1,
            'gradient' => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)]});
}

print_it($F, 'Filled Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)], 'filled' => 1});
}

print_it($F, 'Vertical Gradient Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon(
        {
            'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)],
            'filled'      => 1,
            'gradient'    => {
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Horizontal Gradient Polygon Test');
$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon(
        {
            'coordinates' => [rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY), rand($XX), rand($YY)],
            'filled'      => 1,
            'gradient'    => {
                'direction' => 'horizontal',
                'start' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                },
                'end' => {
                    'red'   => rand(256),
                    'green' => rand(256),
                    'blue'  => rand(256)
                }
            }
        }
    );
} ## end while (time < $s)

print_it($F, 'Testing Bezier Curves');

$s = time + $factor;
while (time < $s) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    my @coords = ();
    foreach my $c (1 .. int(rand(20))) {
        push(@coords, int(rand($XX)), int(rand($YY)));
    }
    $F->bezier({'coordinates' => \@coords, 'points' => 100});
} ## end while (time < $s)

{
    print_it($F, 'Testing TrueType Font Rendering (random height/width)');

    my $g = time + $factor;
    while (time < $g) {
        my $x  = int(rand(600 * $xm));
        my $y  = int(rand(900 * $ym));
        my $h  = ($YY < 128) ? (6 + rand(60)) : (8 + int(rand(300 * $ym)));
        my $ws = ($XX < 256) ? rand(2) : rand(4);

        my $b = $F->ttf_print(
            {
                'x'            => $x,
                'y'            => $y,
                'height'       => $h,
                'wscale'       => $ws,
                'color'        => sprintf('%02x%02x%02x', int(rand(256)), int(rand(256)), int(rand(256))),
                'text'         => 'GFB',
                'bounding_box' => 1,
                'center'       => 3
            }
        );
        if (defined($b)) {
            $b->{'x'} = rand($F->{'XX_CLIP'} - $b->{'pwidth'});
            $F->ttf_print($b);
        }
    } ## end while (time < $g)
}
print_it($F, 'Testing flood fill');
if ($XX > 255) {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [220 * $xm, 190 * $ym, 1520 * $xm, 80 * $xm, 1160 * $xm, $YY, 960 * $xm, 540 * $ym, 760 * $xm, 1080 * $ym]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [1270 * $xm, 570 * $ym, 970 * $xm, 170 * $ym, 600 * $xm, 500 * $ym]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->circle({'x' => 500 * $xm, 'y' => 320 * $ym, 'radius' => 100 * $xm});

    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 240 * $xm, 'y' => 200 * $ym});

    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 960 * $xm, 'y' => 440 * $ym});
} else {
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->polygon({'coordinates' => [$center_x, 3, 3, $YY - 3, $center_x, $center_y, $XX - 3, $YY - 4]});
    $F->set_color({'red' => rand(256), 'green' => rand(256), 'blue' => rand(256)});
    $F->fill({'x' => 3, 'y' => 3});
} ## end else [ if ($XX > 255) ]

print_it($F, 'Testing Color Replace (clipping on)');

my $x = $F->{'XRES'} / 4;
my $y = $F->{'YRES'} / 4;
$F->splash();
$F->clip_set({'x' => $x, 'y' => $y, 'xx' => $x * 3, 'yy' => $y * 3});
my $r = 128;
my $g = 0;
my $b = 0;
$s = time + $factor;
while (time < $s) {
    my $R = int(rand(256));
    my $G = int(rand(256));
    my $B = int(rand(256));
    $F->replace_color(
        {
            'old_red'   => $r,
            'old_green' => $g,
            'old_blue'  => $b,
            'new_red'   => $R,
            'new_green' => $G,
            'new_blue'  => $B
        }
    );
    ($r, $g, $b) = ($R, $G, $B);
} ## end while (time < $s)

print_it($F, 'Testing Color Replace (clipping off)');

$F->splash();

$F->clip_reset();

$r = 128;
$g = 0;
$b = 0;
$s = time + $factor;
while (time < $s) {
    my $R = int(rand(256));
    my $G = int(rand(256));
    my $B = int(rand(256));
    $F->replace_color(
        {
            'old_red'   => $r,
            'old_green' => $g,
            'old_blue'  => $b,
            'new_red'   => $R,
            'new_green' => $G,
            'new_blue'  => $B
        }
    );
    ($r, $g, $b) = ($R, $G, $B);
} ## end while (time < $s)

print_it($F, 'Testing Image load (different sizes)');

$s = time + $factor;
while (time < $s) {
    my $image = $F->load_image(
        {
            'x'      => 0,
            'y'      => 0,
            'width'  => rand($XX),
            'height' => rand($YY),
            'file'   => 'images/testpattern.jpg'
        }
    );
    $F->blit_write($image);
} ## end while (time < $s)

my $image = $F->load_image(
    {
        'x'      => 0,
        'y'      => 0,
        'width'  => $XX,
        'height' => $YY,
        'file'   => 'images/testpattern.jpg'
    }
);
$F->blit_write($image);
sleep $factor;

print_it($F, 'Testing Image blitting');

$image = $F->load_image(
    {
        'x'      => 0,
        'y'      => 0,
        'width'  => min(640, $XX / 2),
        'height' => min(405, $YY / 2),
        'file'   => 'images/RWBY_Faces.png'
    }
);
$s = time + $factor;
while (time < $s) {
    $image->{'x'} = abs(rand($XX - $image->{'width'}));
    $image->{'y'} = abs(rand($YY - $image->{'height'}));
    $F->blit_write($image);
}
# sleep $factor;

print_it($F, 'Testing Monochrome Image blitting');

$image->{'image'} = $F->monochrome({'image' => $image->{'image'}, 'bits' => $F->{'BITS'}});
$s = time + $factor;
while (time < $s) {
    $image->{'x'} = abs(rand($XX - $image->{'width'}));
    $image->{'y'} = abs(rand($YY - $image->{'height'}));
    $F->blit_write($image);
}

$F->clip_reset();
$F->cls('ON');

exit(0);

sub print_it {
    my $fb      = shift;
    my $message = shift;

    $fb->normal_mode();
    $fb->clip_reset();
    $fb->cls();
    unless ($XX < 256) {
        $fb->or_mode();

        my $b = $fb->ttf_print(
            {
                'x'            => 5 * $xm,
                'y'            => max(9, 20 * $ym),
                'height'       => max(10, 20 * $ym),
                'color'        => '00FF00',
                'text'         => $message,
                'bounding_box' => 1,
                'center'       => $fb->{'CENTER_X'},
                'antialias'    => 1
            }
        );
        $fb->ttf_print($b);
        $fb->clip_set({'x' => 0, 'y' => $b->{'pheight'}, 'xx' => $XX, 'yy' => $YY});
        $fb->normal_mode();
    } else {
        print "$message\n";
    }
} ## end sub print_it

__END__

