package PLP::Tie::Headers;

use strict;
use warnings;
use Carp;

our $VERSION = '1.00';

=head1 PLP::Tie::Headers

Makes a hash case insensitive, and sets some headers. <_> equals <->, so C<$foo{CONTENT_TYPE}> is
the same as C<$foo{'Content-Type'}>.

	tie %somehash, 'PLP::Tie::Headers';

This module is part of the PLP internals and probably not of much use to others.

=cut

sub TIEHASH {
	return bless [ # Defaults
		{
			'Content-Type'  => 'text/html',
			'X-PLP-Version' => $PLP::VERSION,
		},
		{
			'content-type'  => 'Content-Type',
			'x-plp-version' => 'X-PLP-Version',
		},
		1  # = content-type untouched
	], $_[0];
}

sub FETCH {
	my ($self, $key) = @_;
	if ($self->[2] and defined $self->[0]->{'Content-Type'}) {
		my $utf8 = eval { grep {$_ eq "utf8"}  PerlIO::get_layers(*STDOUT) };
		$self->[0]->{'Content-Type'} .= '; charset=utf-8' if $utf8;
		$self->[2] = 0;
	}
	$key =~ tr/_/-/;
	defined ($key = $self->[1]->{lc $key}) or return;
	return $self->[0]->{$key};
}

sub STORE {
	my ($self, $key, $value) = @_;
	$key =~ tr/_/-/;
	if ($PLP::sentheaders) {
		my @caller = caller;
		die "Can't set headers after sending them at " .
		    "$caller[1] line $caller[2].\n(Output started at " .
		    "$PLP::sentheaders->[0] line $PLP::sentheaders->[1].)\n"
	}
	if (defined $self->[1]->{lc $key}){
		$key = $self->[1]->{lc $key};
	} else {
		$self->[1]->{lc $key} = $key;
	}
	$self->[2] = 0 if $key eq 'Content-Type';
	return ($self->[0]->{$key} = $value);
}

sub DELETE {
	my ($self, $key) = @_;
	$key =~ tr/_/-/;
	delete $self->[0]->{$key};
	return delete $self->[1]->{lc $key};
}

sub CLEAR {
	my $self = $_[0];
	return (@$self = ());
}

sub EXISTS {
	my ($self, $key) = @_;
	$key =~ tr/_/-/;
	return exists $self->[1]->{lc $key};
}

sub FIRSTKEY {
	my $self = $_[0];
	keys %{$self->[0]};
	return each %{ $self->[0] }; # Key only, Tie::Hash doc is wrong.
}

sub NEXTKEY {
	return each %{ $_[0]->[0] };
}

1;

