use v5.12.0;
use warnings;
use Data::Dump qw/pp dd/;
#use Test::More;

goto TEST_TIE;

warn "--------- Test Overload";

my $scalar_ovl;
$$scalar_ovl = "x";
bless $scalar_ovl, "OVL_DEMO";
warn "--- $scalar_ovl";

my $hash_ovl = {a=>42};
bless $hash_ovl, "OVL_DEMO";
warn "--- $hash_ovl->{a}";

TEST_TIE:
warn "--------- Test TIE";



my $hash1 = { a=> 1 };
my $h_shadow1 = Proxy::shadow_ref($hash1);
warn "--- $h_shadow1->{a}";
exit;
my $hash2 = { a=> {b=>2} };
my $h_shadow2 = Proxy::shadow_ref($hash2);
warn "--- $h_shadow2->{a}{b}";

exit;


my $hash_tie = { a=> 1 } ;#{ b =>3 } };

# GOTCHA originalwerte gehen verloren und müssen kopiert werden
my $hash_shadow;
tie %$hash_shadow, "Proxy::Hash";
%$hash_shadow = %$hash_tie; 
warn "--- $hash_shadow->{a}";


my $hash_tie2 = { a=> { b =>3 } };

# GOTCHA originalwerte gehen verloren und müssen kopiert werden
my $hash_shadow2;
tie %$hash_shadow2, "Proxy::Hash";
%$hash_shadow2 = %$hash_tie2; 
warn "--- $hash_shadow2->{a}{b}";

BEGIN {
    package OVL_DEMO;
    use Data::Dump qw/pp dd/;

    use overload
      '""'  => \&string,
        '%{}' => \&hash,
          '@{}' => \&array, 
            ;


    sub string {
        my ($self) = @_;
        warn "OVERLOAD string:";
        return __PACKAGE__." = ".$$self;
    }

    # --- GOTCHAs
    # beim overload bekommt man nicht den Key gesagt
    # zugriff auf SELF unterliegt auch dem overload,
    # reblessing nötig um deep recursion zu vermeiden
    sub hash {
        my $self = shift;
        my ($other, $swap) = @_;
        warn "OVERLOAD hash";
        bless $self, "DUMMY";
        #warn pp
        my $val = __PACKAGE__." = ". $self->{a};
        bless $self, __PACKAGE__;
        return { a=> $val };
    }


    package Proxy;
    sub shadow_ref {
        my $val = shift ;

        my $shadow;
        if (ref $val eq "HASH") {
            tie %$shadow, "Proxy::Hash";
            %$shadow = %$val;
        } elsif (ref $val eq "ARRAY") {
            tie @$shadow, "ArrayDiver";
            @$shadow = @$val;
        } elsif (ref $val eq "") {      # scalar
            #        tie $$shadow, "ScalarDiver";
            $$shadow = $$val;
        } else {
            die "unknown case <", ref $val,">";
        }
        return $shadow

    }
    
    package Proxy::Hash;
    require Tie::Hash;
    use Data::Dump qw/pp dd/;

    our @ISA = qw(Tie::StdHash);

    # GOTCHA TIEHASH bekommt nur die Klasse gesagt nicht die ref
    # sub TIEHASH {
    #     my ( $class ) = @_ ;
    #     warn "TIEHASH", pp \@_;
    # }
    # GOTCHA wann wird new aufgerufen?
    # sub new {
    #     my ( $class ) = @_ ;
    #     warn "TIEHAsh->new", pp \@_;
    # }

    sub FETCH {
        my ( $self, $key ) = @_ ;
        # warn "FETCH('$key')",pp $self;
        my $val = $self->{$key};
        # my $shadow;
        # if (ref $val eq "HASH") {
        #     tie %$shadow, "Proxy::Hash";
        #     %$shadow = %$val;
        # } else {
        #     $shadow = "TIEHASH FETCH: " .$self->{$key};
        # }

        #return $shadow;
        return Proxy::shadow_ref($val)
    }
}
