use 5.012;
use warnings;
use Data::Dump;


package main;

my %hash;
@hash{"a".."c"} = 40 ..42;              # init

say \%hash;

#my $copy =

ddx "TIE: ",
tie                                     # bind wrapper
  %hash,
  'Data::Proxy::TieHash',
  \%hash;                               # redundant, why?


ddx \%hash;

#undef $copy;


say $hash{a};

say @hash{"a".."c"};

delete $hash{b};

say @hash{"a".."c"};

untie %hash;                            # unbind wrapper

say @hash{"a".."c"};


BEGIN {
    package Data::Proxy::TieHash;
    require Tie::Hash;
    use Scalar::Util qw/blessed/;
    use Data::Dump;
    use Carp;

    
    our @ISA = qw(Tie::ExtraHash);
    # perldoc Tie::Hash
    # All methods provided by default, define 
    # only those needing overrides
    # Accessors access the storage in %{$_[0][0]};
    # TIEHASH should return an array reference with the first element
    # being the reference to the actual storage

    sub _report {
        #  uncomment to trace
        #carp "Doing \U$_[0]\E of $_[1] at $_[2].\n"
    };

    sub DELETE {
        my ($obj, $key) =  @_;
         my ($storage, $orig) = @$obj;
        #ddx $storage;                      # TODO whats Meta? 

        #ddx tied $orig;
        
        _report('DELETE', $orig, $key);

        my $class = blessed $obj;
        undef $obj;
        untie %{$orig};
        my $ret = delete $orig->{$key};
        tie %{$orig}, $class, $orig;
        return $ret;
    }

    sub FETCH {
        goto &FETCH1;                   # use implementation
    }

    sub FETCH0 {
        _report('FETCH', $_[0][1], $_[1]); 

        untie %{$_[0][1]};
        my $ret = $_[0][1]->{$_[1]};
        tie %{$_[0][1]}, 'Data::Proxy::TieHash', $_[0][1];
        return "<$ret>" if defined $ret;
        return undef;
    }


    sub FETCH1 {
        my ($obj, $key) = @_;
        my ($storage, $orig) = @$obj;

        _report('FETCH', $orig, $key);

        my $class = blessed $obj;
        undef $obj;                     # avoid warning
        untie %{$orig};
        my $ret = $orig->{$key};
        tie %{$orig}, $class, $orig;
        return "<$ret>" if defined $ret;
        return undef;
    }

}


exit;



$hash{b}=2;
delete $hash{a};
say $hash{b};

my $hr = \%hash;
say $hr->{b};


my %h= ("a".."f");

my $obj = Data::Proxy->new(\%h);

say $obj->{a};

BUG:
exit;








sub _hash {
    my %clone = ("a".."z");
    #say \%clone;
    warn  $clone{a}; 
    tie %clone, 'Data::Proxy::TieHash', {};

    warn  $clone{a}; 
    # my $cr = \%clone;
    # warn  $cr->{a};

    # return \%clone;
}

#_hash();

#sub TIEHASH  { bless [ %, @_], $p }




# package Data::Proxy;

# use overload
#   '%{}' => "hash",
#   ;

# sub hash {
#     warn "OVL hash called";
#     bless $_[0], "Data::Proxy::_dummy_";
#     my %clone = %{$_[0]};
#     bless $_[0], "Data::Proxy";

#     my %tie;
#     tie %tie, 'Data::Proxy::TieHash', {};
#     %tie = %clone;
#     return \%tie;

# }

# sub new {
#     my ($class,$ref) = @_;
#     return bless $ref, $class;
# }
