use strict;
use warnings;
use Test::More;

use Symbol::Rename();
my $CLASS = 'Symbol::Rename';

BEGIN { *symbol_exists = Symbol::Rename->can('_symbol_exists') }

sub get_glob_ref {
    my ($class, $name) = @_;
    no strict 'refs';
    return \*{"$class\::$name"};
}

BEGIN {
    package XXX;

    our (%xxx, @xxx);
    our $xxx = 'xxx';
    sub xxx { 'xxx' }
}

ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'CODE'),   '&XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'ARRAY'),  '@XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'HASH'),   '%XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'SCALAR'), '$XXX::xxx exists');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'),   '&XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'ARRAY'),  '@XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'HASH'),   '%XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'SCALAR'), '$XXX::yyy does not exist');

Symbol::Rename->import(-package => 'XXX', xxx => 'yyy');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'CODE'), '&XXX::xxx removed');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'),   '&XXX::yyy added');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'ARRAY'),  '@XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'HASH'),   '%XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'SCALAR'), '$XXX::xxx exists');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'ARRAY'),  '@XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'HASH'),   '%XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'SCALAR'), '$XXX::yyy does not exist');

Symbol::Rename->import(-package => 'XXX', yyy => 'xxx');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'), '&XXX::yyy removed');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'CODE'),   '&XXX::xxx added');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'ARRAY'),  '@XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'HASH'),   '%XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'SCALAR'), '$XXX::xxx exists');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'),   '&XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'ARRAY'),  '@XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'HASH'),   '%XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'SCALAR'), '$XXX::yyy does not exist');

XXX->Symbol::Rename::rename_symbols('$xxx' => 'yyy');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'SCALAR'), '$XXX::xxx removed');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'SCALAR'), '$XXX::yyy added');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'CODE'),   '&XXX::xxx added');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'ARRAY'),  '@XXX::xxx exists');
ok(symbol_exists(get_glob_ref('XXX', 'xxx'), 'HASH'),   '%XXX::xxx exists');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'),  '&XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'ARRAY'), '@XXX::yyy does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'yyy'), 'HASH'),  '%XXX::yyy does not exist');
XXX->Symbol::Rename::rename_symbols('$yyy' => 'xxx');

Symbol::Rename->import(-package => 'XXX', xxx => 'yyy', '$xxx' => 'yyy', '%xxx' => 'yyy', '@xxx' => 'yyy');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'CODE'),   '&XXX::yyy exists');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'ARRAY'),  '@XXX::yyy exists');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'HASH'),   '%XXX::yyy exists');
ok(symbol_exists(get_glob_ref('XXX', 'yyy'), 'SCALAR'), '$XXX::yyy exists');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'CODE'),   '&XXX::xxx does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'ARRAY'),  '@XXX::xxx does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'HASH'),   '%XXX::xxx does not exist');
ok(!symbol_exists(get_glob_ref('XXX', 'xxx'), 'SCALAR'), '$XXX::xxx does not exist');

sub exception(&) {
    my $code = shift;
    my $ok = eval { $code->(); 1 };
    return $ok ? undef : $@;
}

like(
    exception { Symbol::Rename->import('-package') },
    qr/No argument provided for option '-package'/,
    "Need to specify an argument to package"
);

like(
    exception { Symbol::Rename->import('-xxx' => 1) },
    qr/Unsupported option\(s\): xxx/,
    "Not all options are valid"
);

like(
    exception { Symbol::Rename->import('abc' => 'cba') },
    qr/Origin symbol '&main::abc' does not exist/,
    "Cannot rename a symbol that does not exist"
);

like(
    exception { Symbol::Rename->import('abc' => 'is') },
    qr/Destination symbol '&main::is' already exists/,
    "Cannot override another symbol"
);

done_testing;
