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

use Data::Dumper;

use lib '/app/tools/common/lib';
use RSApache::Response::XSLT;

use lib '/app/tools/rps/lib';
use RPS::ArtistPayee::Form;
use RPS::ArtistPayee::Command::Show;

use RPS::Payee::ArtistPayeeStatementRecipient;
use RPS::DB::Item::ArtistPayeeStatementRecipient;

use RPS::Command;
use RPS::CommandLog;
use base 'RPS::Command';

sub cmd  { return "edit"; }
sub area { return "artist_payee"; }

use constant kTemplate => '/app/tools/rps/templates/artist_payee/index.xsl';
use constant kMaxRecipients => 5;
use constant kRecipientPostfix => '_Alt';


sub execute {
    my $self = shift;

    # Give any inherited methods the first crack at this.
    # (This checks for login and basic access permissions).
    my $response = $self->SUPER::execute();
    return $response if $response;

    my $id = $self->getParam("ArtistPayeeID");
    my $form = RPS::ArtistPayee::Form->new( artistPayeeID => $id );

    if ( $self->getParam('formSubmit') ) {

        if ( $self->_assignCGIParams($form) && $self->_validateForm($form) ) {
            $form->save();
            $id = $form->getArtistPayeeID();
            RPS::CommandLog::Log( $self, $id );

            # recipients can be added only when statement distribution is set to Online
            if ( $form->getArtistPayeeDistribution() ) {
                $self->_deletePendingStatementRecipients($form);
                $self->_saveStatementRecipients($form);
            }

            my $successMessage = RPS::Message->new( type => "success", code => Common::FormObject::kSuccessFormSubmit );
            my $oCommand = RPS::ArtistPayee::Command::Show->new( msg => $successMessage->toString, ArtistPayeeID => $id );
            return RSApache::Response::Redirect->new( $oCommand->getRedirect() );
        }

        $self->_stayOnFormRaiseError($form);
    }

    $self->{xml}{Form} = $form;

    return RSApache::Response::XSLT->new( $self->{xml}, kTemplate );
}

sub _assignCGIParams {
    my ($self, $form) = @_;

    my $payeeStatus      = $form->assignCGIParams( 'Form', $self->getParams() );
    my $recipientsStatus = $self->_assignCGIParamsRecipients($form);
    return $payeeStatus && $recipientsStatus;
}

sub _validateForm {
    my ($self, $form) = @_;

    my $payeeStatus      = $form->validate();
    my $recipientsStatus = $self->_recipientPostValidate($form);

    return $payeeStatus && $recipientsStatus;
}


sub _stayOnFormRaiseError {
     my ($self, $form) = @_;

    $form->setError(Common::FormObject::kErrFormSubmit);
    $self->addMessageXML( type => "error", code => Common::FormObject::kErrFormSubmit );
    return 1;
}


sub _assignCGIParamsRecipients {
    my ($self, $form) = @_;

    my $subFormPrefix            = 'StatementRecipient';
    my $artistPayeeIDAttr        = $subFormPrefix . '_ArtistPayeeID';
    my $statementRecipientIDAttr = $subFormPrefix . '_StatementRecipientID';
    my $deleteRecipientAttr      = $subFormPrefix . '_WaitingToDelete';

    my $status = 0;
    my $liveItems = 0;
    my @newRecipientsList;
    foreach my $i ( 1 .. kMaxRecipients ) {
        my $hParams = $self->_getSingleRecipientParams(kRecipientPostfix . $i);
        next unless grep {$_} values %$hParams;

        # The '_StatementRecipientID' attribute can be present if we are updating an existing recipient,
        # or empty if this is a new recipient.
        my $recipientID = exists $hParams->{$statementRecipientIDAttr}
            ? $hParams->{$statementRecipientIDAttr}
            : 0;

        # The '_WaitingToDelete' attribute only exists when we try to delete a recipient (existing or non-existing).
        if ( exists $hParams->{$deleteRecipientAttr} && $hParams->{$deleteRecipientAttr} ) {
            # Check if a non-existing item is pending removal
            $recipientID = $hParams->{$deleteRecipientAttr} =~ /^\d+$/
                ? $hParams->{$deleteRecipientAttr}
                : next;
        }

        $liveItems++;
        $hParams->{$artistPayeeIDAttr} = $form->getArtistPayeeID();

        my ($oRecipient) = grep { $_->StatementRecipientID eq $recipientID } @{ $form->getArtistPayeeRecipients() };
        $oRecipient = RPS::Payee::ArtistPayeeStatementRecipient->new() unless $oRecipient;
        if ( $oRecipient->assignCGIParams($subFormPrefix, $hParams) && $oRecipient->validate() ) {
            $status++;
        }

        push @newRecipientsList, $oRecipient;
    }

    # overwrite recipients
    $form->{ArtistPayeeRecipients} = \@newRecipientsList;

    return $liveItems == $status ? 1 : 0;
}

sub _getSingleRecipientParams {
    my ($self, $postfix) = @_;

    my %params;
    while ( my($k, $v) = each %{ $self->getParams() } ) {
        next unless $k =~ /$postfix$/;
        $k =~ s/$postfix$//;
        $params{$k} = $v;
    }

    return \%params;
}

sub _recipientPostValidate {
    my ($self, $form) = @_;

    $valid = 1;

    # Check E-mails for duplicates including main payee's email.
    my $hEmails = {};
    for ( $form->{ArtistPayee}->Email(), $form->{ArtistPayee}->OrigEmail() ) {
        $hEmails->{$_} = 1 if $_;
    }

    # Additional payee recipients' E-mails
    foreach my $oRecipient ( @{ $form->getArtistPayeeRecipients() } ) {
        my $email = $oRecipient->Email();
        if ( exists $hEmails->{$email} ) {
            $oRecipient->{Email}->setError( Common::FormObject::kErrFieldDuplicate );
            $valid = 0;
        }
        $hEmails->{ $oRecipient->Email }++;
    }

    return $valid;
}

sub _saveStatementRecipients {
    my ($self, $form) = @_;

    foreach my $oRecipient ( @{ $form->getArtistPayeeRecipients() } ) {
        next if $oRecipient->WaitingToDelete;
        $oRecipient->save();
    }

    return 1;
}

sub _deletePendingStatementRecipients {
    my ($self, $form) = @_;

    foreach my $oRecipient ( @{ $form->getArtistPayeeRecipients() } ) {
        next unless ( $oRecipient->WaitingToDelete && $oRecipient->StatementRecipientID );
        $oRecipient->delete();
    }

    return 1;
}


1;
