package MZonedHash;

use strict;
use Carp;
use MCoreTools;

### Tying ############################################################################################

sub TIEHASH {
  my ($class, %param) = @_;
  
  my $self = bless {
    Objects => {},
  }, $class;
  $self;
}

sub FETCH {
  my ($self, $key) = @_;
  $self->_type_swap_in_key($key);
  return $self->{Objects}->{$key};
}

sub STORE {
  my ($self, $key, $value) = @_;
  my $zone = $self->_get_zone($key);
  $self->_type_swap_in($zone);
  $self->_type_store_zoned($zone, $key, $value);
  return $self->{Objects}->{$key} = $value;
}

sub DELETE {
  my ($self, $key) = @_;
  my $zone = $self->_get_zone($key);
  $self->_type_swap_in($zone);
  $self->_type_delete_zoned($zone, $key);
  return delete $self->{Objects}->{$key};
}

sub EXISTS {
  my ($self, $key) = @_;
  $self->_type_swap_in_key($key);
  return exists $self->{Objects}->{$key};
}

sub CLEAR    { croak "can't clear a "        . __PACKAGE__; }
sub FIRSTKEY { croak "can't iterate over a " . __PACKAGE__; }
sub NEXTKEY  { croak "can't iterate over a " . __PACKAGE__; }

### Public ############################################################################################

sub delete_value {
  my ($self, $val) = @_;
  while (my ($k, $v) = each %{$self->{Objects}}) {
    next unless $v eq $val;
    delete $self->{Objects}{$k};
    $self->_type_delete_zoned($self->_get_zone($k), $k);
    last;
  }
}

sub swap_out {
  my ($self) = @_;
}

### Private ############################################################################################

sub _type_swap_in_key {
  my ($self, $key) = @_;
  $self->_type_swap_in($self->_get_zone($key));
}

sub _get_zone {
  my ($self, $str) = @_;
  $str =~ s#/[^/]+$## or croak "Bad path string for a ".__PACKAGE__;
  $str;
}

sub _type_swap_in {confess "must be overridden";}

1;
