use strict;
use warnings;

use Test::More;

use lib 't/lib';

use Fey::ORM::Test;
use Fey::Literal::String;
use Fey::Test;
use List::MoreUtils qw( uniq );


Fey::ORM::Test::insert_user_data();
Fey::ORM::Test::insert_message_data();
Fey::ORM::Test::define_live_classes();

plan tests => 16;


{
    Schema->EnableObjectCaches();

    for my $class ( qw( User Message ) )
    {
        ok( $class->meta()->_object_cache_is_enabled(),
            "object cache is enabled in $class after Schema->EnableObjectCaches()" );
    }
}

{
    Schema->DisableObjectCaches();

    for my $class ( qw( User Message ) )
    {
        ok( ! $class->meta()->_object_cache_is_enabled(),
            "object cache is disabled in $class after Schema->DisableObjectCaches()" );
    }
}

{
    Schema->EnableObjectCaches();

    # seed the cache
    User->new( user_id => 1 );
    User->new( user_id => 42 );

    Message->new( message_id => 1 );
    Message->new( message_id => 2 );

    for my $class ( qw( User Message ) )
    {
        my $count = scalar uniq values %{ $class->meta()->_object_cache() };
        is( $count, 2,
            "$class has two unique objects in its cache" );
    }

    Schema->ClearObjectCaches();

    for my $class ( qw( User Message ) )
    {
        my $count = scalar uniq values %{ $class->meta()->_object_cache() };
        is( $count, 0,
            "$class has no objects in its cache after Schema->ClearObjectCaches()" );
    }
}

{
    my $sub =
        sub
        {
            User->insert( username => 'foo' );
        };

    Schema->RunInTransaction($sub);

    ok( User->new( username => 'foo' ),
        'username of foo was inserted via RunInTransaction' );
}

{
    my $sub =
        sub
        {
            User->insert( username => 'bar' );
            die 'should rollback';
        };

    eval { Schema->RunInTransaction($sub) };

    ok( ! User->new( username => 'bar' ),
        'username of bar was not inserted via RunInTransaction because of rollback' );
}

{
    my $sub =
        sub
        {
            Schema->RunInTransaction( sub { User->insert( username => 'baz' ) } );
        };

    Schema->RunInTransaction($sub);

    ok( User->new( username => 'baz' ),
        'username of baz was inserted via nested RunInTransaction' );
}

{
    my $sub =
        sub
        {
            Schema->RunInTransaction( sub { User->insert( username => 'quux' ) } );
            die 'should rollback';
        };

    eval { Schema->RunInTransaction($sub) };

    ok( ! User->new( username => 'quux' ),
        'username of quux was not inserted via nested RunInTransaction because of rollback' );
}

{
    my $sub = sub { return User->insert( username => 'baz2' ) };

    my $user = Schema->RunInTransaction($sub);

    ok( $user,
        'RunInTransaction returns value' );
}

{
    my $sub =
        sub
        {
            Schema->RunInTransaction( sub { return User->insert( username => 'baz3' ) } );
        };

    my $user = Schema->RunInTransaction($sub);

    ok( $user,
        'nested RunInTransaction returns value' );
}

{
    my $sub = sub { my @a = ( 1, 2, 3 ); return @a; };

    my @a = Schema->RunInTransaction($sub);

    is_deeply( \@a, [ 1, 2, 3 ],
               'RunInTransaction respects calling context' );
}

{
    my $sub = sub { Schema->RunInTransaction( sub { my @a = ( 1, 2, 3 ); return @a; } ) };

    my @a = Schema->RunInTransaction($sub);

    is_deeply( \@a, [ 1, 2, 3 ],
               'nested RunInTransaction respects calling context' );
}
