#!perl -T

use strict;
use Test::More qw(no_plan);

use Graphics::Framebuffer;


my $F = Graphics::Framebuffer->new('MALI' => 1,'SPLASH' => 0);
isa_ok($F, 'Graphics::Framebuffer');

my $screen_width  = $F->{'XRES'};
my $screen_height = $F->{'YRES'};
my $XX            = $screen_width;
my $YY            = $screen_height;
my $center_x      = int($screen_width / 2);
my $center_y      = int($screen_height / 2);
my $factor        = $F->{'BITS'} / 16;

my @OK;

$F->normal_mode();
$F->cls();

subtest 'Plot tests' => sub {
    print_it($F,'Plotting Test');
    foreach my $p (1..2000) {
        my $x = int(rand($screen_width));
        my $y = int(rand($screen_height));
        my $p = int(rand(5));
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->plot({'x' => rand($screen_width),'y' => rand($screen_height)});
        push(@OK,[1,"Plot test X=$x, Y=$y"]);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Plot tests');

subtest 'Line draw tests' => sub {
    print_it($F,'Line Test');
    for(my $l=40;$l < $YY;$l += 40) {
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->line({'x' => 0,'y' => $l,'xx' =>$XX, 'yy' => $l});
        push(@OK,[1,'Diagonal line test']);
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->line({'x' => 0,'y' => $l,'xx' =>$l, 'yy' => 40});
        push(@OK,[1,'Diagonal line test']);
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->line({'x' => $XX,'y' => $l,'xx' =>$XX - $l, 'yy' => 40});
        push(@OK,[1,'Rotating line test']);

        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->line({'x' => $XX,'y' => $YY - $l,'xx' =>$XX - $l, 'yy' => 40});
        push(@OK,[1,'Vertical line test']);
    }
    for(my $l=0;$l < $XX;$l += 40) {
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->line({'x' => $l,'y' => 40,'xx' =>$l, 'yy' => $YY});
        push(@OK,[1,'Line test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Line drawing tests');

subtest 'Box frame tests' => sub {
    print_it($F,'Box Test');
    foreach my $p (1..(50 * $factor)) {
        $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)});
        push(@OK,[1,'Box test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Box drawing tests');

subtest 'Filled box tests' => sub {
    print_it($F,'Filled Box Test');
    foreach my $p (1..(30 * $factor)) {
        $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});
        push(@OK,[1,'Filled box test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Filled box testing');

subtest 'Gradient Box tests' => sub {
    print_it($F,'Gradient Box Test');
    foreach my $p (1..(20 * $factor)) {
        $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)
                        }
                    }
                }
        );
        push(@OK,[1,'Gradient filled box test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Gradient box testing');

subtest 'Rounded box tests' => sub {
    print_it($F,'Rounded Box Test');
    foreach my $p (1..(25 * $factor)) {
        $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(20)+1});
        push(@OK,[1,'Box with rounded corners test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Rounded box testing');

subtest 'Filled rounded box tests' => sub {
    print_it($F,'Filled Rounded Box Test');
    foreach my $p (1..(20 * $factor)) {
        $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(80)+1,'filled' => 1});
        push(@OK,[1,'Filled box with rounded corners test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Filled rounded box testing');

subtest 'Gradient filled rounded box tests' => sub {
    print_it($F,'Gradient Rounded Box Test');
    foreach my $p (1..(20 * $factor)) {
        $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(80)+1,'filled' => 1,
                    'gradient' => {
                        'start' => {
                            'red'   => rand(256),
                            'green' => rand(256),
                            'blue'  => rand(256)
                        },
                        'end' => {
                            'red'   => rand(256),
                            'green' => rand(256),
                            'blue'  => rand(256)
                        }
                    }
                }
        );
        push(@OK,[1,'Gradient filled box with rounded corners test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Gradient filled rounded box testing');

subtest 'Circle frame tests' => sub {
    print_it($F,'Circle Test');
    foreach my $p (1..(50 * $factor)) {
        $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
        $F->circle({'x' => rand($XX),'y' => rand($YY),'radius' => rand($center_y)});
        push(@OK,[1,'Circle test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Circle frame testing');

subtest 'Filled circle tests' => sub {
    print_it($F,'Filled Circle Test');
    foreach my $p (1..(25 * $factor)) {
        $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});
        push(@OK,[1,'Filled circle test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Filled circle testing');

subtest 'Gradient filled circle tests' => sub {
    print_it($F,'Gradient Circle Test');
    foreach my $p (1..(25 * $factor)) {
        $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)
                           }
                       }
                   }
        );
        push(@OK,[1,'Gradient filled circle test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Gradient filled circle testing');

subtest 'Ellipse frame tests' => sub {
    print_it($F,'Ellipse Test');
    foreach my $p (1..(50 * $factor)) {
        $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)});
        push(@OK,[1,'Ellipse test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Ellipse frame testing');

subtest 'Filled ellipse tests' => sub {
    print_it($F,'Filled Ellipse Test');
    foreach my $p (1..(20 * $factor)) {
        $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});
        push(@OK,[1,'Filled ellipse test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Filled ellipse testing');

subtest 'Gradient ellipse tests' => sub {
    print_it($F,'Gradient Ellipse Test');
    foreach my $p (1..(20 * $factor)) {
        $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)
                            }
                        }
                    }
        );
        push(@OK,[1,'Gradient filled ellipse test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Gradient filled ellipse testing');

subtest 'Polygon frame tests' => sub {
    print_it($F,'Polygon Test');
    foreach my $p (1..(25 * $factor)) {
        $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)]});
        push(@OK,[1,'Polygon test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Polygon frame testing');

subtest 'Filled polygon tests' => sub {
    print_it($F,'Filled Polygon Test');
    foreach my $p (1..(15 * $factor)) {
        $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});
        push(@OK,[1,'Filled polygon test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Filled polygon testing');

subtest 'Gradient filled polygon tests' => sub {
    print_it($F,'Gradient Polygon Test');
    foreach my $p (1..(15 * $factor)) {
        $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)
                            }
                        }
                    }
        );
        push(@OK,[1,'Gradient filled polygon test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Gradient filled polygon testing');

subtest 'Bezier curve tests' => sub {
    print_it($F,'Testing Bezier Curves');

    foreach my $z (1..(40 * $factor)) {
        $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});
        push(@OK,[1,'Bezier curves test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Bezier curve testing');

TODO: {
    local $TODO = 'Tests may fail if default font is missing';

    subtest 'TrueType rendering tests' => sub {
        print_it($F,'Testing TrueType Font Rendering (random height/width)');

        for(my $c=8; $c < 400; $c+=(20 * $factor)) {
            my $x = int(rand(600));
            my $y = int(rand(900));
            my $h = int(rand(300)) + 8;
            my $ws = rand(4);

            my $b = $F->ttf_print(
                {
                    'x'            => $x,
                     'y'            => $y,
                      'height'       => $c,
                      'wscale'       => $ws,
                      'color'        => sprintf('%x%x%x%x', int(rand(256)), int(rand(256)), int(rand(256)), 255 ),
                      'text'         => 'GFB',
                      'bounding_box' => 1,
                      'center'       => 3
                }
            );
            my $ok = 1;
            if (defined($b)) {
                $b->{'x'} = rand($F->{'XX_CLIP'} - $b->{'pwidth'});
                $F->ttf_print($b);
            } else {
                $ok = 0;
            }
            push(@OK,[$ok,'TrueType Test']);
        }
        send_results(@OK);@OK = ();
    };
    ok(1,'TrueType rendering testing');
}

subtest 'Flood fill tests' => sub {
    print_it($F,'Testing flood fill');
    $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
    $F->polygon({'coordinates' => [220,190,$XX-400,80,$center_x+200,$YY,$center_x,$center_y,$center_x-200,$YY]});
    $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
    $F->polygon({'coordinates' => [$center_x+310,$center_y+30, $center_x+10,170, 600,500]});
    $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
    $F->circle({'x' => 500,'y' => 320,'radius' => 100});

    $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
    $F->fill({'x' => $center_x+100, 'y' => $center_y + 100});
    push(@OK,[1,'Flood fill test']);
    $F->set_color({'red' => rand(256),'green' => rand(256),'blue' => rand(256)});
    $F->fill({'x' => $center_x, 'y' => $center_y - 100});
    push(@OK,[1,'Flood fill test']);
    send_results(@OK);@OK = ();
};
ok(1,'Flood fill tests');

subtest 'Color replace tests with clipping on' => sub {
    print_it($F,"Testing Color Replace (clipping on, $factor times)");

    $F->clip_set({'x' => 100,'y' => 100,'xx' => $F->{'XRES'} - 100,'yy' => $F->{'YRES'} - 100});

    $F->splash();
    my $r = 128;
    my $g = 0;
    my $b = 0;
    foreach my $re (1..$factor) {
        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);
        push(@OK,[1,'Replace color clipping on test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Color replace testing with clipping on');

subtest 'Color replace tests with clipping off' => sub {
    print_it($F,'Testing Color Replace (clipping off, ' . (5 * $factor) . ' times)');

    $F->splash();

    $F->clip_reset();

    my $r = 128;
    my $g = 0;
    my $b = 0;
    foreach my $re (1..(5 * $factor)) {
        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);
        push(@OK,[1,'Replace color clipping off test']);
    }
    send_results(@OK);@OK = ();
};
ok(1,'Color replace testing with clipping off');

$F->cls();

exit(0);

sub print_it {
    my $fb      = shift;
    my $message = shift;
    $fb->or_mode();
    $fb->clip_reset();
    $fb->cls();

    my $b = $fb->ttf_print(
        {
            'x'            => 5,
              'y'            => 30,
              'height'       => 30,
              'color'        => '00FF00',
              'text'         => $message,
              'bounding_box' => 1,
              'center'       => 0,
              'antialias'    => 1
        }
    );
    $fb->ttf_print($b);
    $fb->clip_set({'x' => 0, 'y' => $b->{'pheight'},'xx' => $XX,'yy' => $YY});
    $fb->normal_mode();
}

sub send_results {
    my @ok = @_;

    foreach my $ok (@ok) {
        ok(@{$ok});
    }
}

__END__

