package Apache::Voodoo::Validate::date;

$VERSION = "3.0200";

use strict;
use warnings;

use base("Apache::Voodoo::Validate::Plugin");

sub config {
	my ($self,$c) = @_;
	my @e;

	if (defined($c->{valid})) {
		if ($c->{valid} =~ /^(past|future)$/ ) {
			$self->{valid} = $c->{valid};
		}
		elsif (ref($c->{valid}) ne "CODE") {
			push(@e,"'valid' must be either 'past','future', or a subroutine reference");
		}
	}

	if (defined($c->{now})) {
		if (ref($c->{now}) eq "CODE") {
			$self->{now} = $c->{now};
		}
		else {
			push(@e,"'now' must be a subroutine reference");
		}
	}
	else {
		$self->{now} = \&_default_now;
	}

	if (defined($c->{parser})) {
		if (ref($c->{parser}) eq "CODE") {
			$self->{parser} = $c->{parser};
		}
		else {
			push(@e,"'parser' must be a subroutine reference");
		}
	}
	else {
		$self->{parser} = \&_default_parser;
	}

	return @e;
}

sub valid {
	my ($self,$v) = @_;

	my $e;
	my ($y,$m,$d) = $self->{parser}->($v);

	if (defined($y)   &&
		defined($m)   &&
		defined($d)   &&
		$y =~ /^\d+$/ &&
		$m =~ /^\d+$/ &&
		$d =~ /^\d+$/) {

		$v = sprintf("%04d-%02d-%02d",$y,$m,$d);

		if (defined($self->{'valid'})) {	# supresses warnings.
			if ($self->{'valid'} eq "past" && $v gt $self->{now}->()) {
				$e = 'PAST';
			}
			elsif ($self->{'valid'} eq "future" && $v le $self->{now}->()) {
				$e = 'FUTURE';
			}
		}
	}
	else {
		$e = 'BAD';
	}

	return $v,$e;
}

sub _default_now {
	my @tp = localtime();
	return sprintf("%04d-%02d-%02d",$tp[5]+1900,$tp[4]+1,$tp[3]);
}

sub _default_parser {
	my $date = shift;

	# Number of days in each month
	my %md = (1  => 31,
	          2  => 29,
	          3  => 31,
	          4  => 30,
	          5  => 31,
	          6  => 30,
	          7  => 31,
	          8  => 31,
	          9  => 30,
	          10 => 31,
	          11 => 30,
	          12 => 31);

	# Split the date up into month day year
	my ($m,$d,$y);

	if ($date =~ /^\d?\d\/\d?\d\/\d{4}$/) {
		($m,$d,$y) = split("/",$date, 3);
	}
	elsif ($date =~ /^\d{4}-\d?\d-\d?\d$/) {
		($y,$m,$d) = split("-",$date, 3);
	}
	else {
		return undef;
	}

	#Strip off any leading 0s
	$m *= 1;
	$d *= 1;
	$y *= 1;

	# If the month isn't within a valid range return
	if ($m !~ /^\d+$/ || $m < 1 || $m > 12) {
		return undef;
	}

	# Check to see if the day is valid on leap years
	if ($m == 2 && $d == 29) {
		unless (($y%4 == 0 && $y%100 != 0) || $y%400 == 0){
			return undef;
		}
	}

	# If the day isn't within a valid range return
	if ($d !~ /^\d+$/ || $d < 1 || $d > $md{$m}) {
		return undef;
	}

	# make sure the year is four digits
	if ($y !~ /^\d+$/ || $y < 1000 || $y > 9999) {
		return undef;
	}

	return $y,$m,$d;
}

1;

################################################################################
# Copyright (c) 2005-2010 Steven Edwards (maverick@smurfbane.org).
# All rights reserved.
#
# You may use and distribute Apache::Voodoo under the terms described in the
# LICENSE file include in this package. The summary is it's a legalese version
# of the Artistic License :)
#
################################################################################