#!/usr/bin/env perl
use strict;
use warnings;
use Benchmark qw(cmpthese timethese);

use FindBin qw($RealBin);
use lib "$RealBin/../blib/lib", "$RealBin/../blib/arch";  # From bench/ to blib/
use lib '/Users/lnation/Semantic/Doubly/blib/lib', '/Users/lnation/Semantic/Doubly/blib/arch';

use doubly;

# Suppress redefinition warnings from Doubly (it loads XS twice due to lib path issues)
no warnings 'redefine';
use Doubly;
use warnings 'redefine';

print "=" x 60, "\n";
print "Benchmark: doubly (new SV registry) vs Doubly (original)\n";
print "=" x 60, "\n\n";

my $iterations = 10000;

print "1. Creating and destroying empty lists ($iterations iterations)\n";
cmpthese($iterations, {
    'doubly' => sub {
        my $list = doubly->new();
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new();
        $list->destroy();
    },
});

print "\n2. Creating list with initial value ($iterations iterations)\n";
cmpthese($iterations, {
    'doubly' => sub {
        my $list = doubly->new(42);
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new(42);
        $list->destroy();
    },
});

print "\n3. Adding 100 items ($iterations/10 iterations)\n";
cmpthese($iterations/10, {
    'doubly' => sub {
        my $list = doubly->new();
        $list->add($_) for 1..100;
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new();
        $list->add($_) for 1..100;
        $list->destroy();
    },
});

print "\n4. bulk_add 100 items ($iterations/10 iterations)\n";
cmpthese($iterations/10, {
    'doubly' => sub {
        my $list = doubly->new();
        $list->bulk_add(1..100);
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new();
        $list->bulk_add(1..100);
        $list->destroy();
    },
});

print "\n5. Navigation: start/end/next/prev ($iterations iterations)\n";
{
    my $d_list = doubly->new();
    $d_list->bulk_add(1..100);
    my $D_list = Doubly->new();
    $D_list->bulk_add(1..100);
    
    cmpthese($iterations, {
        'doubly' => sub {
            my $l = $d_list->start;
            $l = $l->next for 1..10;
            $l = $l->end;
            $l = $l->prev for 1..10;
        },
        'Doubly' => sub {
            my $l = $D_list->start;
            $l = $l->next for 1..10;
            $l = $l->end;
            $l = $l->prev for 1..10;
        },
    });
    
    $d_list->destroy();
    $D_list->destroy();
}

print "\n6. Data access (get) ($iterations iterations)\n";
{
    my $d_list = doubly->new(42);
    my $D_list = Doubly->new(42);
    
    cmpthese($iterations, {
        'doubly' => sub {
            my $x = $d_list->data;
        },
        'Doubly' => sub {
            my $x = $D_list->data;
        },
    });
    
    $d_list->destroy();
    $D_list->destroy();
}

print "\n7. Data access (set) ($iterations iterations)\n";
{
    my $d_list = doubly->new(42);
    my $D_list = Doubly->new(42);
    
    cmpthese($iterations, {
        'doubly' => sub {
            $d_list->data(99);
        },
        'Doubly' => sub {
            $D_list->data(99);
        },
    });
    
    $d_list->destroy();
    $D_list->destroy();
}

print "\n8. Length access ($iterations iterations)\n";
{
    my $d_list = doubly->new();
    $d_list->bulk_add(1..100);
    my $D_list = Doubly->new();
    $D_list->bulk_add(1..100);
    
    cmpthese($iterations, {
        'doubly' => sub {
            my $x = $d_list->length;
        },
        'Doubly' => sub {
            my $x = $D_list->length;
        },
    });
    
    $d_list->destroy();
    $D_list->destroy();
}

print "\n9. Remove from start ($iterations/10 iterations)\n";
cmpthese($iterations/10, {
    'doubly' => sub {
        my $list = doubly->new();
        $list->bulk_add(1..50);
        $list->remove_from_start for 1..50;
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new();
        $list->bulk_add(1..50);
        $list->remove_from_start for 1..50;
        $list->destroy();
    },
});

print "\n10. Find operation ($iterations/10 iterations)\n";
{
    my $d_list = doubly->new();
    $d_list->bulk_add(1..100);
    my $D_list = Doubly->new();
    $D_list->bulk_add(1..100);
    
    cmpthese($iterations/10, {
        'doubly' => sub {
            $d_list->find(sub { $_[0] == 50 });
        },
        'Doubly' => sub {
            $D_list->find(sub { $_[0] == 50 });
        },
    });
    
    $d_list->destroy();
    $D_list->destroy();
}

print "\n11. Complex data (hashrefs) ($iterations/10 iterations)\n";
cmpthese($iterations/10, {
    'doubly' => sub {
        my $list = doubly->new({ name => 'test', value => 42 });
        $list->add({ name => 'item', value => $_ }) for 1..10;
        my $d = $list->data;
        $list->destroy();
    },
    'Doubly' => sub {
        my $list = Doubly->new({ name => 'test', value => 42 });
        $list->add({ name => 'item', value => $_ }) for 1..10;
        my $d = $list->data;
        $list->destroy();
    },
});

print "\n", "=" x 60, "\n";
print "Benchmark complete!\n";
