package HTML::Element::MetaHash;

use Carp;
use HTML::Element;

sub TIEHASH {
    my $self = shift;
    my $tree = shift;

    unless (ref($tree) eq 'HTML::Element') {
        croak "must tie to an HTML::Element";
    }

    my $node = {
        TREE => $tree,
    };

    bless $node => $self;
}

sub FETCH {
    my $self = shift;
    my $key  = shift;
    if (my $element = $self->{TREE}->look_down(_tag => 'meta', name => $key)) {
        $element->attr('content');
    }
}

sub STORE {
    my $self = shift;
    my $key  = shift;
    my $val  = shift;

    # First, see if there's already such a meta element to stick the new value in.
    if (my $element = $self->{TREE}->look_down(_tag => 'meta', name => $key)) {
        $element->attr('content', $val);
    } else {
        my $meta = HTML::Element->new('meta', name => $key, content => $val);
        my $head = $self->{TREE}->look_down(_tag => 'head');
        unless (defined $head) {
            $head = HTML::Element->new('head');
            $self->{TREE}->unshift_content($head);
        }
        $head->push_content($meta);
    }
}

sub DELETE {
    my $self = shift;
    my $key  = shift;
    if (my $element = $self->{TREE}->look_down(_tag => 'meta', name => $key)) {
        $element->delete();
    }
}

sub CLEAR {
    my $self = shift;
    $_->delete() foreach $self->{TREE}->look_down(_tag => 'meta');
}

sub EXISTS {
    my $self = shift;
    my $key  = shift;
    (scalar $self->{TREE}->look_down(_tag => 'meta', name => $key)) ? 1 : 0;
}

sub FIRSTKEY {
    my $self = shift;
    if (my $element = $self->{TREE}->look_down(_tag => 'meta')) {
        $element->attr('name');
    }
}

sub NEXTKEY {
    my $self = shift;
    my $prev = shift;

    my $seen_prev = 0;

    my $finder = sub {
        my $el = shift;
        if ($el->attr('name') eq $prev) {
            $seen_prev = 1;
            0;
        } elsif ($seen_prev) {
            1;
        }
    };

    if (my $element = $self->{TREE}->look_down(_tag => 'meta', $finder)) {
        $element->attr('name');
    }
}

sub DESTROY {}

1;

