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

use strict;
use warnings;

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

use lib '/app/tools/rps/lib';
use RPS::DB::Item::Payor;
use RPS::DB::Item::TrackLicense;
use RPS::DB::Item::CATrackLicense;
use RPS::DB::Item::NewArtistContract;

use RPS::ArtistPayee::ArtistPayeeAccount;
use RPS::LabelPayee::LabelPayeeAccount;
use RPS::Publisher::US::PublisherAccount;
use RPS::Publisher::CA::PublisherAccount;

use Common::FormObject;
use base 'Common::FormObject';

use constant kValidLogoExtensions => qw( gif jpg jpeg png );

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

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

    my %properties;
    if ( $args{_dbItem} ) {
        $self->_propertiesFromDBItem( \%properties, $args{_dbItem} );
    } elsif ( $args{payorID} ) {
        $self->_propertiesFromDB( \%properties, $args{payorID} );
    } else {
        $self->_propertiesFromDefaults( \%properties );
    }

    my $runType = $args{runType};
    $self->_initProperties( \%properties, $runType );

    return $self;
}

sub _propertiesFromDB {
    my ( $self, $hrProperties, $id ) = @_;

    my $dbItem = RPS::DB::Item::Payor->Lookup( payor_id => $id );
    $self->_propertiesFromDBItem( $hrProperties, $dbItem );
}

sub _propertiesFromDBItem {
    my ( $self, $hrProperties, $dbItem ) = @_;

    $hrProperties->{payor_id}           = $dbItem->payor_id;
    $hrProperties->{name}               = $dbItem->name;
    $hrProperties->{street_address}     = $dbItem->street_address;
    $hrProperties->{street_address_2}   = $dbItem->street_address_2;
    $hrProperties->{street_address_3}   = $dbItem->street_address_3;
    $hrProperties->{city}               = $dbItem->city;
    $hrProperties->{state_province}     = $dbItem->state_province;
    $hrProperties->{country_code}       = $dbItem->country_code;
    $hrProperties->{postal_code}        = $dbItem->postal_code;
    $hrProperties->{phone_number}       = $dbItem->phone_number;
    $hrProperties->{fax_number}         = $dbItem->fax_number;
    $hrProperties->{cycle_code}         = $dbItem->cycle_code;
    $hrProperties->{begin_month_code}   = $dbItem->begin_month_code;
    $hrProperties->{comments}           = $dbItem->comments;
    $hrProperties->{tax_id}             = $dbItem->tax_id;
    $hrProperties->{client_payor_id}    = $dbItem->client_payor_id;
    $hrProperties->{inactive}           = $dbItem->inactive;
    $hrProperties->{is_default}         = $dbItem->is_default;
    $hrProperties->{email}              = $dbItem->email;
    $hrProperties->{show_logo}          = $dbItem->show_logo;
    $hrProperties->{supplier_code}      = $dbItem->supplier_code;
    $hrProperties->{ap1_supplier_code}  = $dbItem->ap1_supplier_code;
    $hrProperties->{avp_supplier_code}  = $dbItem->avp_supplier_code;
    $hrProperties->{dvd1_supplier_code} = $dbItem->dvd1_supplier_code;

    $hrProperties->{date_created}  = $dbItem->date_created;
    $hrProperties->{created_by}    = $dbItem->created_by;
    $hrProperties->{date_modified} = $dbItem->date_modified;
    $hrProperties->{modified_by}   = $dbItem->modified_by;

    $hrProperties->{artist_payee_min_payment} = $dbItem->artist_payee_min_payment;
    $hrProperties->{label_payee_min_payment} = $dbItem->label_payee_min_payment;
    $hrProperties->{us_publisher_min_payment} = $dbItem->us_publisher_min_payment;
    $hrProperties->{ca_publisher_min_payment} = $dbItem->ca_publisher_min_payment;
}

sub _propertiesFromDefaults {
    my ( $self, $hrProperties ) = @_;
}

sub _initProperties {
    my ( $self, $props ) = @_;

    $self->{PayorID} = Common::FormObject::Scalar->new( value => $props->{payor_id}, readOnly => 1 );
    $self->{Name}           = Common::FormObject::Scalar::String->new( value => $props->{name}, required => 1 );
    $self->{StreetAddress}  = Common::FormObject::Scalar::String->new( value => $props->{street_address} );
    $self->{StreetAddress2} = Common::FormObject::Scalar::String->new( value => $props->{street_address_2} );
    $self->{StreetAddress3} = Common::FormObject::Scalar::String->new( value => $props->{street_address_3} );
    $self->{City}           = Common::FormObject::Scalar::String->new( value => $props->{city} );
    $self->{StateProvince}  = Common::FormObject::Scalar::String->new( value => $props->{state_province} );
    $self->{CountryCode}    = Common::FormObject::Scalar::String->new( value => $props->{country_code} );
    $self->{PostalCode}     = Common::FormObject::Scalar::String->new( value => $props->{postal_code} );
    $self->{PhoneNumber}    = Common::FormObject::Scalar::String->new( value => $props->{phone_number} );
    $self->{FaxNumber}      = Common::FormObject::Scalar::String->new( value => $props->{fax_number} );
    $self->{CycleCode}      = Common::FormObject::Scalar->new( value => $props->{cycle_code} );         # ??? required ???
    $self->{BeginMonthCode} = Common::FormObject::Scalar->new( value => $props->{begin_month_code} );
    $self->{Comments}      = Common::FormObject::Scalar::String->new( value => $props->{comments} );
    $self->{TaxID}         = Common::FormObject::Scalar::String->new( value => $props->{tax_id} );
    $self->{ClientPayorID} = Common::FormObject::Scalar::String->new( value => $props->{client_payor_id} );
    $self->{Email}         = Common::FormObject::Scalar::String->new( value => $props->{email} );
    $self->{Inactive}  = Common::FormObject::Scalar::Boolean->new( value => $props->{inactive} );
    $self->{IsDefault} = Common::FormObject::Scalar::Boolean->new( value => $props->{is_default}, readOnly => 1 );
    $self->{ShowLogo}  = Common::FormObject::Scalar::Boolean->new( value => $props->{show_logo} );
    $self->{SupplierCode}     = Common::FormObject::Scalar::String->new( value => $props->{supplier_code} );
    $self->{AP1SupplierCode}  = Common::FormObject::Scalar::String->new( value => $props->{ap1_supplier_code} );
    $self->{AVPSupplierCode}  = Common::FormObject::Scalar::String->new( value => $props->{avp_supplier_code} );
    $self->{DVD1SupplierCode} = Common::FormObject::Scalar::String->new( value => $props->{dvd1_supplier_code} );

    $self->{CreatedDate}  = Common::FormObject::Scalar::DateTime->new( value => $props->{date_created},  readOnly => 1 );
    $self->{ModifiedDate} = Common::FormObject::Scalar::DateTime->new( value => $props->{date_modified}, readOnly => 1 );
    $self->{CreatedBy}    = Common::FormObject::Scalar::UserName->new( value => $props->{created_by},    readOnly => 1 );
    $self->{ModifiedBy}   = Common::FormObject::Scalar::UserName->new( value => $props->{modified_by},   readOnly => 1 );

    $self->{ArtistPayeeMinPayment}  = Common::FormObject::Scalar::Decimal->new( value => $props->{artist_payee_min_payment}, precision => '0.2'  );
    $self->{LabelPayeeMinPayment}  = Common::FormObject::Scalar::Decimal->new( value => $props->{label_payee_min_payment}, precision => '0.2'  );
    $self->{USPublisherMinPayment}  = Common::FormObject::Scalar::Decimal->new( value => $props->{us_publisher_min_payment}, precision => '0.2'  );
    $self->{CAPublisherMinPayment}  = Common::FormObject::Scalar::Decimal->new( value => $props->{ca_publisher_min_payment}, precision => '0.2' );

    my $numLicenses;
    my $numCALicenses;
    my $numContracts;
    my $logo;
    my $logoWeb;

    my $payorID = $self->PayorID();
    if ($payorID) {

        # JPK - This turns out to be expensive, slow, and not necessary.
        #
        $numLicenses = RPS::DB::Item::TrackLicense->GetCountByPayorID($payorID);

        $numCALicenses = RPS::DB::Item::CATrackLicense->GetCountByPayorID($payorID);

        $numContracts = RPS::DB::Item::NewArtistContract->GetCountByPayor($payorID);

        my $clientID = Common::RSApp::GetClientID();

        # Checking for a logo.
        my @validExtensions = kValidLogoExtensions;

        my $filePath = "/app/tools/common/production/images/payor_logos/$clientID/$payorID.";

        foreach my $ext (@validExtensions) {
            if ( -e $filePath . $ext ) {
                $logo = $filePath . $ext;
                last();
            }
        }

        if ($logo) {

            # Making it easier to use the image source in the templates.
            $logoWeb = $logo;
            $logoWeb =~ s/\/app\/tools\/common//;

        }
    }

    $self->{LogoSource}    = $logo;
    $self->{LogoSourceWeb} = $logoWeb;

    $self->{ContractCount}  = $numContracts;
    $self->{CALicenseCount} = $numCALicenses;
    $self->{USLicenseCount} = $numLicenses;

    $self->{IsLinked} = ( $numLicenses || $numCALicenses || $numContracts ? 1 : 0 );
}

sub save {
    my ($self) = @_;

    my $createFlag = 0;
    my $dbObj;
    if ( $self->PayorID() ) {
        $dbObj = RPS::DB::Item::Payor->Lookup( payor_id => $self->PayorID() );
    } else {
        $createFlag = 1;
        $dbObj      = RPS::DB::Item::Payor->Create();
    }

    # set fields here
    #
    $dbObj->name( $self->Name() );
    $dbObj->street_address( $self->StreetAddress() );
    $dbObj->street_address_2( $self->StreetAddress2() );
    $dbObj->street_address_3( $self->StreetAddress3() );
    $dbObj->city( $self->City() );
    $dbObj->state_province( $self->StateProvince() );
    $dbObj->country_code( $self->CountryCode() );
    $dbObj->postal_code( $self->PostalCode() );
    $dbObj->email( $self->Email() );
    $dbObj->phone_number( $self->PhoneNumber() );
    $dbObj->fax_number( $self->FaxNumber() );
    $dbObj->tax_id( $self->TaxID() );
    $dbObj->cycle_code( $self->CycleCode() );
    $dbObj->begin_month_code( $self->BeginMonthCode() );
    $dbObj->comments( $self->Comments() );
    $dbObj->client_payor_id( $self->ClientPayorID() );
    $dbObj->show_logo( $self->ShowLogo() );
    $dbObj->supplier_code( $self->SupplierCode() );
    $dbObj->ap1_supplier_code( $self->AP1SupplierCode() );
    $dbObj->avp_supplier_code( $self->AVPSupplierCode() );
    $dbObj->dvd1_supplier_code( $self->DVD1SupplierCode() );

    $dbObj->artist_payee_min_payment( $self->ArtistPayeeMinPayment() );
    $dbObj->label_payee_min_payment( $self->LabelPayeeMinPayment() );
    $dbObj->us_publisher_min_payment( $self->USPublisherMinPayment() );
    $dbObj->ca_publisher_min_payment( $self->CAPublisherMinPayment() );

    # see sub activate() or inactivate()
    $dbObj->inactive( $self->Inactive() );

    # save db item
    #
    $dbObj->save();

    my $payor_id = ($self->PayorID ? $self->PayorID : $dbObj->payor_id);

    $self->_assignArtistPayeeMinPayment(payor_id => $payor_id) if ($self->ArtistPayeeMinPayment());
    $self->_assignLabelPayeeMinPayment(payor_id => $payor_id) if ($self->LabelPayeeMinPayment());
    $self->_assignUSPublisherMinPayment(payor_id => $payor_id) if ($self->USPublisherMinPayment());
    $self->_assignCAPublisherMinPayment(payor_id => $payor_id) if ($self->CAPublisherMinPayment());

    # reload object
    #
    $self->_init( _dbItem => $dbObj );
}

sub delete {
    my ($self) = @_;

    if ( $self->IsLinked() ) {
        return undef;
    }

    my $dbItem = RPS::DB::Item::Payor->Lookup( payor_id => $self->PayorID() );
    $dbItem->delete();
}

sub makeDefault {
    my ($self) = @_;

    my $id = $self->PayorID();
    assert($id);

    # You can't make an inactive payor the default!
    #
    if ( $self->Inactive() ) {
        return 0;
    }

    # Get the current default db item.
    #
    my $oldDefault = RPS::DB::Item::Payor->GetDefault();
    if ($oldDefault) {
        $oldDefault->is_default(0);
        $oldDefault->save;
    }

    # Now make this object the default.
    # jpk - Note that this property is set as readOnly - I don't want it to get accidentally set somehow
    # through the normal cgi property assignment code.
    # However, this means that I can't just set the property directly, either.
    # That is why I am going to 'pave over' the old property with a new Scalar object.
    #
    my $data = RPS::DB::Item::Payor->Lookup( payor_id => $id );
    $data->is_default(1);
    $data->save();
    $self->{IsDefault} = Common::FormObject::Scalar::Boolean->new( value => 1, readOnly => 1 );

    return 1;
}

sub _isLinked {
    my ($self) = @_;

    return 0 if ( !$self->PayorID() );

    # Is this Payor attached to a License/Contract?
    #
    my $licenses  = RPS::DB::Item::TrackLicense->GetByPayorID( $self->PayorID() );
    my $contracts = RPS::DB::Item::NewArtistContract->GetByPayor( $self->PayorID() );
    return 1 if ( $licenses && $contracts && $licenses->size > 0 || $contracts->size > 0 );

    return 0;
}

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

    my $payor_id = $args{payor_id} || 0;
    (Common::Log::Print("Unable to set Artist Payee Min Payment due to missed payor ID") and return undef) unless $payor_id;

    my $payees = RPS::DB::Item::Payor->GetArtistPayees($payor_id);

    while ($payees->hasNext()) {
        $self->{Account} = RPS::ArtistPayee::ArtistPayeeAccount->new( artistPayeeID => $payees->next->{artist_payee_id}, payorID => $payor_id );
        $self->{Account}->{MinPayment} = $self->ArtistPayeeMinPayment;
        $self->{Account}->save;
    }
}

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

    my $payor_id = $args{payor_id} || 0;
    (Common::Log::Print("Unable to set Artist Payee Min Payment due to missed payor ID") and return undef) unless $payor_id;

    my $payees = RPS::DB::Item::Payor->GetLabelPayees($payor_id);

    while ($payees->hasNext()) {
        $self->{Account} = RPS::LabelPayee::LabelPayeeAccount->new( labelPayeeID => $payees->next->{label_payee_id}, payorID => $payor_id );
        $self->{Account}->{MinPayment} = $self->LabelPayeeMinPayment;
        $self->{Account}->save;
    }
}

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

    my $payor_id = $args{payor_id} || 0;
    (Common::Log::Print("Unable to set Artist Payee Min Payment due to missed payor ID") and return undef) unless $payor_id;

    my $payees = RPS::DB::Item::Payor->GetPublisherPayees($payor_id);

    while ($payees->hasNext()) {
        $self->{Account} = RPS::Publisher::US::PublisherAccount->new( publisherID => $payees->next->{publisher_id}, payorID => $payor_id );
        $self->{Account}->{MinPayment} = $self->USPublisherMinPayment;
        $self->{Account}->save;
    }
}

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

    my $payor_id = $args{payor_id} || 0;
    (Common::Log::Print("Unable to set Artist Payee Min Payment due to missed payor ID") and return undef) unless $payor_id;

    my $payees = RPS::DB::Item::Payor->GetCAPublisherPayees($payor_id);

    while ($payees->hasNext()) {
        $self->{Account} = RPS::Publisher::CA::PublisherAccount->new( publisherID => $payees->next->{ca_publisher_id}, payorID => $payor_id );
        $self->{Account}->{MinPayment} = $self->CAPublisherMinPayment;
        $self->{Account}->save;
    }
}

1;
