package Period::MonthPeriod;

use strict;

#use warnings;
use Carp;
use Date::Calc;

use lib '/app/tools/common/lib';
use Common::Util;

use constant DB_TABLE    => "period_month";
use constant PERIOD_TYPE => "M";

# private attributes
my @attributes     = qw(month_id date_begin date_end quarter year month);
my @xml_attributes = qw(PeriodID PeriodType StartDate EndDate Quarter Year Month);

use lib '/app/tools/data_classes/lib';
use Item;
use base 'Item';

# --------------------------------
# Constructor
# --------------------------------
sub new {
    my $class = shift;
    my %args  = @_;

    my $self = $class->SUPER::new(@_);
    $self->{dbo} = new Common::RSDB(%args);

    $self->_init(%args);

    return $self;
}

sub _init {
    my $self = shift;
    my %args = @_;

    # initialize user properties
    foreach (@attributes) {
        $self->{$_} = undef;
    }

    # initialize user objects
    $self->{errstr} = undef;

    # are we loading an existing Period?
    my $id = $args{period_id} || $args{month_id};
    if ( $id > 0 ) {
        $self->Load( month_id => $id );
    }
}

# --------------------------------
# Properties
# (month_id date_begin date_end quarter year);
# --------------------------------
sub PeriodID {
    my $self = shift;
    $self->{month_id};
}

sub PeriodType {
    return PERIOD_TYPE();
}

sub StartDate {
    my $self = shift;
    return $self->{date_begin};
}

sub EndDate {
    my $self = shift;
    return $self->{date_end};
}

sub Quarter {
    my $self = shift;
    return $self->{quarter};
}

sub Month {
    my $self = shift;
    return $self->{month};
}

sub Year {
    my $self = shift;
    return $self->{year};
}

sub GetObjectXML {
    my $self = shift;

    my $xml = $self->SUPER::GetObjectXML(@xml_attributes);

    # set period xml, this one, the dates and values for next/previous
    # we might want to add some date formatting later
    # start_month => substr(Date::Calc::Month_to_Text($start_month), 0, 3),
    my ( $s_year, $s_month, $s_day ) = split( '-', $self->StartDate );
    my $start_href = { Day => $s_day, Month => substr( Date::Calc::Month_to_Text($s_month), 0, 3 ), Year => $s_year };

    my ( $e_year, $e_month, $e_day ) = split( '-', $self->EndDate );
    my $end_href = { Day => $e_day, Month => substr( Date::Calc::Month_to_Text($e_month), 0, 3 ), Year => $e_year };

    $xml->{StartDateDisp} = $start_href;
    $xml->{EndDateDisp}   = $end_href;
    $xml->{PrevPeriodID}  = $self->GetPrevPeriodID();
    $xml->{NextPeriodID}  = $self->GetNextPeriodID();

    return $xml;
}

# look in agg_q_summary (month_id)
sub GetPrevPeriodID {
    my $self = shift;

    # TODO: confirm query with Sam after agg tables are built.
    # this class uses the global dbo (client=0), but
    # we need client specific db access here and the ClientID
    # of the class is different from the ClientID of the dbo.
    my $dbo  = new Common::RSDB( client_id => $self->ClientID );
    my $sql  = "SELECT max(month_id) as previous_id FROM agg_m_summary WHERE month_id < " . $self->PeriodID;
    my $sth  = $dbo->DoCmd($sql);
    my $href = $sth->fetchrow_hashref() if ($sth);
    if ($href) {
        return $href->{previous_id};
    } else {
        return undef;
    }
}

sub GetNextPeriodID {
    my $self = shift;

    # TODO: confirm query with Sam after agg tables are built.
    # this class uses the global dbo (client=0), but
    # we need client specific db access here and the ClientID
    # of the class is different from the ClientID of the dbo.
    my $dbo  = new Common::RSDB( client_id => $self->ClientID );
    my $sql  = "SELECT min(month_id) as next_id FROM agg_m_summary WHERE month_id > " . $self->PeriodID;
    my $sth  = $dbo->DoCmd($sql);
    my $href = $sth->fetchrow_hashref() if ($sth);
    if ($href) {
        return $href->{next_id};
    } else {
        return undef;
    }
}

sub Error {
    my $self = shift;
    $self->{errstr};
}

# -------------------------------
# Public Methods
# -------------------------------
sub LoadCurrent {
    my $self = shift;
    my $sql  = "SELECT max(month_id) FROM agg_m_summary";
    my $sth  = $self->{dbo}->DoCmd($sql);
    my $aref = $sth->fetchrow_arrayref() if $sth;

    return undef unless ( $aref && $aref->[0] );
    $self->Load( period_id => $aref->[0] );
}

sub Load {
    my $self      = shift;
    my %args      = @_;
    my $period_id = $args{period_id};

    ## this data is in RSCOMMON, so we have to connect there first.
    my $dbo_c = new Common::RSDB( client_id => 0 );

    my $select_sql;
    if ( defined $period_id && $period_id =~ /^\d+$/ ) {
        $select_sql = "SELECT * FROM " . DB_TABLE . " WHERE month_id=$period_id";
    } else {
        $self->{errstr} = "period_id ($period_id) not specified or not valid";
        return undef;
    }

    my $sth = $dbo_c->DoCmd($select_sql);
    if ( !defined $sth ) {
        $self->{errstr} = "database error: " . $DBI::errstr;
        return undef;
    }

    my $href = $sth->fetchrow_hashref();
    if ( !$href ) {
        $self->{errstr} = "no period defined for period_id=$period_id";
        return undef;
    }

    $self->_load($href);

    return 1;
}

# -------------------------------
# Private Methods
# -------------------------------
sub _load {
    my $self = shift;
    my $href = shift;

    map { $self->{$_} = $href->{$_} } @attributes;
}

###
1;    # Play nicely.
###
