#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#------------------------------------------------------------
package RPS::DateRange;

use strict;
use warnings;
use Date::Calc;

use lib '/app/tools/common/lib';
use Common::Util qw(decodeDateMysql);
use Common::RSApp;
use Common::Assert;

use lib '/app/tools/rps/lib';
use Common::FormObject;
use RPS::DB::Item::Client;
use base 'Common::FormObject';

# these should probably go in the client XMLObject eventually
#
use constant kPeriodMonth		=> 'M';
use constant kPeriodQuarter		=> 'Q';
use constant kPeriodSemiAnnual	=> 'S';
use constant kPeriodAnnual		=> 'A';

sub _init
{
	my ($self, %args) = @_;

	$self->SUPER::_init(%args);
}


sub _initWithHashRef
{
	my ($self, $href) = @_;

	$self->{CurrentDate}	= Common::FormObject::Scalar::String->new(value => $href->{currentDate});
	$self->{StartDate}		= Common::FormObject::Scalar::String->new(value => $href->{startDate});
	$self->{EndDate}		= Common::FormObject::Scalar::String->new(value => $href->{endDate});
	$self->{PreviousDate}	= Common::FormObject::Scalar::String->new(value => $href->{previousDate});
	$self->{NextDate}		= Common::FormObject::Scalar::String->new(value => $href->{nextDate});
	$self->{Type}			= Common::FormObject::Scalar->new(value => $href->{type});
}

# Static method to return proper date range calss
#
sub GetMechanicalDateRangeObject
{
	my ($date) = @_;

	# get client db obj
	#
	my $clientObj = RPS::DB::Item::Client->Lookup(client_id => Common::RSApp::GetClientID());
	return undef if(!defined $clientObj);

	return GetDateRangeObject(date => $date, type => $clientObj->royalty_period_mechanical);
}

sub GetDateRangeObject
{
	my (%args) = @_;

	my $date = $args{date};
	my $type = $args{type};

	# validate date
	#
	my ($year, $month, $day);
	if (! (($year, $month, $day) = Date::Calc::Decode_Date_US($date))
	 && ! (($year, $month, $day) = Date::Calc::Decode_Date_EU($date))
	 && ! (($year, $month, $day) = decodeDateMysql($date)))
	{
		return undef;
	}

	my $dateRangeObj;
	if(RPS::DateRange::kPeriodMonth() eq uc $type)
	{
		$dateRangeObj = RPS::DateRange::Month->new(year => $year, month => $month, day => $day);
	}
	elsif(RPS::DateRange::kPeriodQuarter() eq uc $type)
	{
		$dateRangeObj = RPS::DateRange::Quarter->new(year => $year, month => $month, day => $day);
	}
	elsif(RPS::DateRange::kPeriodSemiAnnual() eq uc $type)
	{
		$dateRangeObj = RPS::DateRange::SemiAnnual->new(year => $year, month => $month, day => $day);
	}
	elsif(RPS::DateRange::kPeriodAnnual() eq uc $type)
	{
		$dateRangeObj = RPS::DateRange::Annual->new(year => $year, month => $month, day => $day);
	}
	else
	{
		# just default to month range for now
		#
		$dateRangeObj = RPS::DateRange::Month->new(year => $year, month => $month, day => $day);
	}

	return $dateRangeObj;
}

# utility to parse either a "date" parameter
# or a "year" "month" and "day" parameters.
#
sub _parseDate
{
	my %args = @_;

	my ($year, $month, $day);

	if($args{date})
	{
		if (! (($year, $month, $day) = Date::Calc::Decode_Date_US($args{date}))
		 && ! (($year, $month, $day) = Date::Calc::Decode_Date_EU($args{date}))
		 && ! (($year, $month, $day) = decodeDateMysql($args{date})))
		{
			return undef;
		}

	}
	elsif($args{year} && $args{month} && $args{day})
	{
		$year = $args{year};
		$month = $args{month};
		$day = $args{day} || 1;
	}

	return ($year, $month, $day);
}



package RPS::DateRange::Month;
use base 'RPS::DateRange';

sub _init
{
    my ($self, %args) = @_;

	$self->SUPER::_init(%args);

	my ($year, $month, $day) = RPS::DateRange::_parseDate(%args);

	my $href = {};
	if($year && $month && $day)
	{
		$href->{currentDate}	= sprintf("%04d-%02d-%02d", $year, $month, $day);
		$href->{startDate}		= sprintf("%04d-%02d-%02d", $year, $month, 1);
		$href->{endDate}		= sprintf("%04d-%02d-%02d", $year, $month, Date::Calc::Days_in_Month($year, $month));

		# we need the next and previous dates, too
		#
		$href->{previousDate}	= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, -1));
		$href->{nextDate}		= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, 1));
		$href->{type}			= RPS::DateRange::kPeriodMonth;

		$self->SUPER::_initWithHashRef($href);
	}

	return $self;
}



package RPS::DateRange::Quarter;
use base 'RPS::DateRange';


sub _init
{
    my ($self, %args) = @_;

	$self->SUPER::_init(%args);

	my ($year, $month, $day) = RPS::DateRange::_parseDate(%args);

	my $href = {};
	if($year && $month && $day)
	{
		$href->{currentDate}	= sprintf("%04d-%02d-%02d", $year, $month, $day);

		my ($startMonth, $endMonth);

		if(($month % 3) != 1)
		{
			# if $startMonth is 2, 5, 8, 11 (mod 3 == 2),
			# 	then substract 1
			# else $startMonth is 3, 6, 9, or 12 (mod 3 == 0)
			# 	so substract 2.
			$startMonth = ($month % 3) ? $month - 1 : $month - 2;
		}
		else
		{
			# $startMonth is 1, 4, 7, or 10,
			# so it's already the first month
			# of the quarter.
			#
			$startMonth = $month;
		}
		$endMonth = $startMonth + 2;

		$href->{startDate}		= sprintf("%04d-%02d-%02d", $year, $startMonth, 1);
		$href->{endDate}		= sprintf("%04d-%02d-%02d", $year, $endMonth, Date::Calc::Days_in_Month($year, $endMonth));

		# we need the next and previous dates, too
		#
		$href->{previousDate}	= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, -3));
		$href->{nextDate}		= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, 3));
		$href->{type}			= RPS::DateRange::kPeriodQuarter;

		$self->SUPER::_initWithHashRef($href);
	}

	return $self;
}


package RPS::DateRange::SemiAnnual;
use base 'RPS::DateRange';

sub _init
{
    my ($self, %args) = @_;

	$self->SUPER::_init(%args);

	my ($year, $month, $day) = RPS::DateRange::_parseDate(%args);

	my $href = {};
	if($year && $month && $day)
	{
		$href->{currentDate}	= sprintf("%04d-%02d-%02d", $year, $month, $day);

		my ($startMonth, $endMonth);

		if($month >= 7)
		{
			$startMonth = 7;
			$endMonth = 12;
		}
		else
		{
			$startMonth = 1;
			$endMonth = 6;
		}

		$href->{startDate}		= sprintf("%04d-%02d-%02d", $year, $startMonth, 1);
		$href->{endDate}		= sprintf("%04d-%02d-%02d", $year, $endMonth, Date::Calc::Days_in_Month($year, $endMonth));

		# we need the next and previous dates, too
		#
		$href->{previousDate}	= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, -6));
		$href->{nextDate}		= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 0, 6));
		$href->{type}			= RPS::DateRange::kPeriodSemiAnnual;

		$self->SUPER::_initWithHashRef($href);
	}

	return $self;
}



package RPS::DateRange::Annual;
use base 'RPS::DateRange';

sub _init
{
    my ($self, %args) = @_;

	$self->SUPER::_init(%args);

	my ($year, $month, $day) = RPS::DateRange::_parseDate(%args);

	my $href = {};
	if($year && $month && $day)
	{
		$href->{currentDate}	= sprintf("%04d-%02d-%02d", $year, $month, $day);

		$href->{startDate}		= sprintf("%04d-%02d-%02d", $year, 1, 1);
		$href->{endDate}		= sprintf("%04d-%02d-%02d", $year, 12, 31);

		# we need the next and previous dates, too
		#
		$href->{previousDate}	= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, -1, 0));
		$href->{nextDate}		= sprintf("%04d-%02d-%02d", Date::Calc::Add_Delta_YM($year, $month, $day, 1, 0));
		$href->{type}			= RPS::DateRange::kPeriodAnnual;

		$self->SUPER::_initWithHashRef($href);
	}

	return $self;
}



###
1;#
###
