package Period::RoyaltyPeriod;

use strict;

#use warnings;
use Carp;

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

use constant DB_TABLE => "period";

# private attributes
my @attributes     = qw(period_id name start_date end_date);
my @xml_attributes = qw(PeriodID Name StartDate EndDate);

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->_init(%args);

    return $self;
}

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

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

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

    # are we loading an existing User?
    if ( defined $args{period_id} ) {
        $self->Load( period_id => $args{period_id} );
    }
}

# --------------------------------
# Properties
# (period_id start_date end_date);
# --------------------------------
sub PeriodID {
    my $self = shift;
    $self->{period_id};
}

sub Name {
    my $self = shift;

    # setting the value
    if (@_) {
        my ($rvalue) = @_;
        if ( $rvalue ne $self->{name} ) {
            $self->{name}  = $rvalue;
            $self->{dirty} = 1;
        }
    }
    return $self->{name};
}

sub StartDate {
    my $self = shift;

    # setting the value
    if (@_) {
        my ($rvalue) = @_;
        if ( $rvalue ne $self->{start_date} ) {
            $self->{start_date} = $rvalue;
            $self->{dirty}      = 1;
        }
    }
    return $self->{start_date};
}

sub EndDate {
    my $self = shift;

    # setting the value
    if (@_) {
        my ($rvalue) = @_;
        if ( $rvalue ne $self->{end_date} ) {
            $self->{end_date} = $rvalue;
            $self->{dirty}    = 1;
        }
    }
    return $self->{end_date};
}

sub MaxID {
    my $self = shift;

    # setting the value
    if (@_) {
        my ($rvalue) = @_;
        $self->{max_id} = $rvalue;
    }
    return $self->{max_id};
}

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 $end_href = {};
    if ( defined $self->EndDate && $self->EndDate ne '' ) {
        my ( $e_year, $e_month, $e_day ) = split( '-', $self->EndDate );
        $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;
}

sub GetPrevPeriodID {
    my $self = shift;

    if ( $self->PeriodID == 0 ) {
        return $self->{max_id} || undef;
    } elsif ( $self->PeriodID == 1 ) {
        return undef;
    } else {
        return $self->PeriodID - 1;
    }
}

sub GetNextPeriodID {
    my $self = shift;

    if ( $self->PeriodID == 0 ) {
        return undef;
    } elsif ( $self->PeriodID == $self->MaxID ) {
        return 0;
    } else {
        return $self->PeriodID + 1;
    }
}

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

# -------------------------------
# Public Methods
# -------------------------------
sub LoadCurrent {
    my $self = shift;

    return $self->Load( period_id => 0 );
}

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

    my $select_sql;
    if ( defined $period_id && $period_id =~ /^\d+$/ ) {

        # select a.*, b.max_id from (select * from period where period_id=0) a, (select max(period_id) as max_id from period) b
        $select_sql =
            "SELECT A.*, B.max_id FROM"
          . " (SELECT * FROM "
          . DB_TABLE
          . " WHERE period_id="
          . $self->{dbo}->DBQuote($period_id) . ") A,"
          . " (SELECT max(period_id) as max_id from period) B";
    } else {
        $self->{errstr} = "period_id ($period_id) not specified or not valid";
        return undef;
    }

    my $sth = $self->{dbo}->DoCmd($select_sql);

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

    my $href = $sth->fetchrow_hashref();

    if ( !defined $href || $sth->rows == 0 ) {
        if ( $period_id == 0 ) {

            # create the current period
            my $insert_sql = "INSERT INTO " . DB_TABLE . " (period_id, start_date, date_created) VALUES (0, NOW(), NOW())";
            $sth = $self->{dbo}->DoCmd($insert_sql);
            if ( !defined $sth ) {
                $self->{errstr} = "database error: " . $DBI::errstr;
                return undef;
            }

            # reload it into this object
            $sth = $self->{dbo}->DoCmd($select_sql);
            if ( !defined $sth ) {
                $self->{errstr} = "database error: " . $DBI::errstr;
                return undef;
            }
            $href = $sth->fetchrow_hashref();
        } else {
            $self->{errstr} = "no file record for period_id=$period_id";
            return undef;
        }
    }

    $self->_load($href);

    $self->{dirty} = 0;

    return 1;
}

sub Save {
    my $self = shift;

    return if ( !$self->{dirty} );

    # create sql for saving the user object
    my @set_fields;
    foreach my $attrib (@attributes) {

        # attributes to skip
        next if $attrib =~ /^(period_id)$/;
        my $new_val = $self->{$attrib};
        next if ( !defined $new_val );

        if ( $self->{$attrib} !~ /null/i ) {
            $new_val = $self->{dbo}->DBQuote($new_val);
        }
        push @set_fields, $attrib . "=" . $new_val;
    }

    my $todayAndNow = Common::Util::today_and_now();
    push @set_fields, 'date_created=' . $self->{dbo}->DBQuote($todayAndNow);

    # update or insert?
    if ( defined $self->{period_id} && $self->{period_id} =~ /^\d+$/ ) {
        my $sql = "UPDATE " . DB_TABLE . " SET " . join( ', ', @set_fields ) . " WHERE period_id=" . $self->{period_id};
        $self->{dbo}->DoCmd($sql);
    } else {

        # no auto increment, so we'll do it manually
        my $sql     = "SELECT max(period_id) as max_id FROM " . DB_TABLE;
        my $sth     = $self->{dbo}->DoCmd($sql);
        my $href    = $sth->fetchrow_hashref();
        my $next_id = $href->{max_id} + 1;

        $sql = "INSERT INTO " . DB_TABLE . " SET period_id=$next_id, " . join( ', ', @set_fields );
        $self->{dbo}->DoCmd($sql);
        $self->{period_id} = $next_id;
    }

    $self->{dirty} = 0;

    return 1;

}

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

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

    # special period attr
    if ( $href->{max_id} > 0 ) {
        $self->MaxID( $href->{max_id} );
    }
}

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