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

use strict;
use warnings;
use Carp;

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

use lib '/app/tools/rps/lib';
use RPS::DB::Item::CAPublisher;
use RPS::Publisher::CA::PublisherAccount;
use Common::FormObject;
use RPS::DB::Item::FormDefaults;
use RPS::DB::Item::Payor;

use RPS::Publisher::CA::PublisherSimple;

use base 'RPS::Publisher::CA::PublisherSimple';

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

    my $timer = Common::Timer->new();

    # First, call the inherited method to get it's fields.
    #
    $self->SUPER::_propertiesFromDBItem( $hrProperties, $dbItem );

    # Now we fill in the rest of the stuff.
    #
    $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->{email}             = $dbItem->email;
    $hrProperties->{phone_number}      = $dbItem->phone_number;
    $hrProperties->{fax_number}        = $dbItem->fax_number;
    $hrProperties->{tax_id}            = $dbItem->tax_id;
    $hrProperties->{statement_type_id} = $dbItem->statement_type_id;
    $hrProperties->{affiliate_id}      = $dbItem->affiliate_id;
    $hrProperties->{cycle_code}        = $dbItem->cycle_code;
    $hrProperties->{min_payment}       = $dbItem->min_payment;
    $hrProperties->{begin_month_code}  = $dbItem->begin_month_code;
    $hrProperties->{comments}          = $dbItem->comments;
    $hrProperties->{client_account_id} = $dbItem->client_account_id;
    $hrProperties->{status}            = $dbItem->status;
    $hrProperties->{date_created}      = $dbItem->date_created;
    $hrProperties->{date_modified}     = $dbItem->date_modified;
    $hrProperties->{created_by}        = $dbItem->created_by;
    $hrProperties->{modified_by}       = $dbItem->modified_by;
}

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

    # Call the inherited method first, to let it get the first crack at this.
    #
    $self->SUPER::_initProperties($props);

    # Now finish the job.
    #
    $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}, maxlength => 80 );
    $self->{StateProvince}  = Common::FormObject::Scalar::String->new( value => $props->{state_province}, maxlength => 80 );
    $self->{CountryCode}    = Common::FormObject::Scalar::String->new( value => $props->{country_code} );
    $self->{PostalCode}     = Common::FormObject::Scalar::String->new( value => $props->{postal_code}, maxlength => 15 );
    $self->{Email} = Common::FormObject::Scalar::EmailAddress->new( value => $props->{email}, maxlength => 80 );
    $self->{PhoneNumber} = Common::FormObject::Scalar::PhoneNumber->new( value => $props->{phone_number}, maxlength => 30 );
    $self->{FaxNumber} = Common::FormObject::Scalar::String->new( value => $props->{fax_number}, maxlength => 30 );
    $self->{TaxID}     = Common::FormObject::Scalar::String->new( value => $props->{tax_id},     maxlength => 30 );
    $self->{StatementTypeID} = Common::FormObject::Scalar->new( value => $props->{statement_type_id} );
    $self->{AffiliateID}     = Common::FormObject::Scalar->new( value => $props->{affiliate_id} );
    $self->{CycleCode}       = Common::FormObject::Scalar->new( value => $props->{cycle_code} );
    $self->{MinPayment} = Common::FormObject::Scalar::Money->new( value => $props->{min_payment} );
    $self->{BeginMonthCode} = Common::FormObject::Scalar->new( value => $props->{begin_month_code} );
    $self->{Comments} = Common::FormObject::Scalar::String->new( value => $props->{comments}, maxlength => 0 );
    $self->{ClientAccountID} = Common::FormObject::Scalar::String->new( value => $props->{client_account_id} );
    $self->{Status} = Common::FormObject::Scalar->new( value => $props->{status} );

    # we want to show the number of publishers that
    # have this publisher as an admin or as an agent
    #
    my $adminFor = 0;
    my $agentFor = 0;
    my $coll;
    $coll = RPS::DB::Item::CAPublisher->GetByAdminID( $props->{publisher_id} );
    $adminFor = ( defined $coll ) ? $coll->size : 0;

    $coll = RPS::DB::Item::CAPublisher->GetByAgentID( $props->{publisher_id} );
    $agentFor = ( defined $coll ) ? $coll->size : 0;

    $self->{AdminFor} = Common::FormObject::Scalar->new( value => $adminFor, readOnly => 1 );
    $self->{AgentFor} = Common::FormObject::Scalar->new( value => $agentFor, readOnly => 1 );
    $self->{UpdateAttachedPublishers} = Common::FormObject::Scalar::Boolean->new();

    $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 );

    if ( $self->loadSubs() ) {
        if ( defined $props->{ca_publisher_id} ) {
            my $accounts = RPS::DB::Item::CAPublisherAccount->GetByPublisherID( $props->{ca_publisher_id} );
            while ( my $account = $accounts->next() ) {
                push @{ $self->{Account} }, RPS::Publisher::CA::PublisherAccount->new( _dbItem => $account, readOnly => 1 );
            }
        }

    }

    return $self;
}

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

    my $valid = $self->SUPER::validate();

    if ( $self->StateProvince() && $self->CountryCode() ) {
        if ( $self->CountryCode() eq 'US' ) {
            if ( !RPS::StateList::IsValidState( $self->StateProvince() ) ) {
                $self->{StateProvince}->setError(Common::FormObject::kErrInvalidState);
                $valid = 0;
            }
        }
    }

    return $valid;
}

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

    my $createFlag = 0;
    my $publisherDBObj;
    if ( $self->PublisherID() ) {
        $publisherDBObj = RPS::DB::Item::CAPublisher->Lookup( ca_publisher_id => $self->PublisherID() );
    } else {
        $createFlag     = 1;
        $publisherDBObj = RPS::DB::Item::CAPublisher->Create();
    }

    my $wasAgency = $publisherDBObj->is_agency;
    my $wasAdmin  = $publisherDBObj->is_admin;

    # an agent cannot have an admin/agent set
    #
    if ( $self->IsAgency() ) {
        $self->AgentID(undef);
        $self->AdminID(undef);
    }

    # an admin cannot have an admin set
    #
    if ( $self->IsAdmin() ) {
        $self->AdminID(undef);
    }

    # set fields here
    #
    $publisherDBObj->publisher_name( $self->PublisherName() );
    $publisherDBObj->is_agency( $self->IsAgency() );
    $publisherDBObj->is_admin( $self->IsAdmin() );
    $publisherDBObj->street_address( $self->StreetAddress() );
    $publisherDBObj->street_address_2( $self->StreetAddress2() );
    $publisherDBObj->street_address_3( $self->StreetAddress3() );
    $publisherDBObj->city( $self->City() );
    $publisherDBObj->state_province( $self->StateProvince() );
    $publisherDBObj->country_code( $self->CountryCode() );
    $publisherDBObj->postal_code( $self->PostalCode() );
    $publisherDBObj->email( $self->Email() );
    $publisherDBObj->phone_number( $self->PhoneNumber() );
    $publisherDBObj->fax_number( $self->FaxNumber() );
    $publisherDBObj->tax_id( $self->TaxID() );
    $publisherDBObj->agent_id( $self->AgentID() );
    $publisherDBObj->admin_id( $self->AdminID() );
    $publisherDBObj->statement_type_id( $self->StatementTypeID() );
    $publisherDBObj->affiliate_id( $self->AffiliateID() );
    $publisherDBObj->cycle_code( $self->CycleCode() );
    $publisherDBObj->min_payment( $self->MinPayment() );
    $publisherDBObj->begin_month_code( $self->BeginMonthCode() );
    $publisherDBObj->comments( $self->Comments() );
    $publisherDBObj->client_account_id( $self->ClientAccountID() );
    $publisherDBObj->status( $self->Status() );

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

    my $publisher_id = $publisherDBObj->ca_publisher_id;
    $self->_processCAPublisherMinPayment(publisher_id => $publisher_id);

    # ----------------------------------------------------------------
    # Some clean-up code used to support "fixing" a user error where
    # they mistakenly create a publisher as an agent (or admin), then
    # attach a bunch of publishers to it, then realize this publisher
    # really should have been an admin (or agent).
    # ----------------------------------------------------------------
    #
    # if we changed from being an admin or agent then
    # we need to fix any publishers that are linked to this
    # publisher via agent_id or admin_id. we will skip ones
    # we can't resolve. UupdateAttachedPublishers is a checkbox
    # the user checks to indicate they want this "fix" to occur.
    #
    # this handles the two cases:
    # 	1. Was Agency or Admin and switched to Agency or Admin
    # 	2. Was Agency or Admin is now neither
    #
    if ( $self->UpdateAttachedPublishers() ) {
        my $collection;

        # Publisher was Admin or Agent and is now neither:
        # remove this agent/admin from all attached publishers
        #
        if ( !$self->IsAgency() && !$self->IsAdmin() ) {
            if ($wasAgency) {

                # get all publishers that have this Publisher set as their Agent
                #
                $collection = RPS::DB::Item::CAPublisher->GetByAgentID( $self->PublisherID() );
                while ( $collection->hasNext() ) {
                    my $dbItem = $collection->next();
                    $dbItem->agent_id(undef);
                    $dbItem->save();
                }
            } elsif ($wasAdmin) {

                # get all publishers that have this Publisher set as their Admin
                #
                $collection = RPS::DB::Item::CAPublisher->GetByAdminID( $self->PublisherID() );
                while ( $collection->hasNext() ) {
                    my $dbItem = $collection->next();
                    $dbItem->admin_id(undef);
                    $dbItem->save();
                }
            }
        }

        # Publisher was Agency, is now Admin:
        # switch attached publishers to use this as an admin,
        # unless they already have an admin
        #
        elsif ( $wasAgency && $self->IsAdmin() ) {

            # get all publishers that have this Publisher set as their Agent
            #
            $collection = RPS::DB::Item::CAPublisher->GetByAgentID( $self->PublisherID() );
            while ( $collection->hasNext() ) {
                my $dbItem = $collection->next();
                if ( !$dbItem->admin_id ) {
                    $dbItem->agent_id(undef);
                    $dbItem->admin_id( $self->PublisherID() );
                    $dbItem->save();
                }
            }
        }

        # Publisher was Admin, is now Agent:
        # switch attached publishers to use this as an agent,
        # unless they already have an agent
        #
        elsif ( $wasAdmin && $self->IsAgency() ) {

            # get all publishers that have this Publisher set as their Admin
            #
            $collection = RPS::DB::Item::CAPublisher->GetByAdminID( $self->PublisherID() );
            while ( $collection->hasNext() ) {
                my $dbItem = $collection->next();
                if ( !$dbItem->agent_id ) {
                    $dbItem->admin_id(undef);
                    $dbItem->agent_id( $self->PublisherID() );
                    $dbItem->save();
                }
            }
        }
    }

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

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

    # Take some (not necessarily all) of these fields and make them defaults.
    #
    # Note that this does _not_ imply that we are actually saving this form's data.
    # Just that we are saving it's stuff as a default.
    # (We need to apply this to the liquidation list, too, I'm thinking...)
    #
    my %newDefaults;
    $newDefaults{cycle_code}  = $self->CycleCode();
    $newDefaults{min_payment} = $self->MinPayment();

    # Save these new defaults.
    #
    RPS::DB::Item::FormDefaults::ReplaceFormPropertyValues( 'RPS::Publisher::CA::Publisher', \%newDefaults );
}

# Accessors
#
sub Account {
    my $self = shift @_;
    if ( $self->{Advance} ) {
        return $self->{Advance}{AdvanceAccount};
    } else {
        return undef;
    }
}

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

    my $publisher_id = $args{publisher_id} || 0;
    (Common::Log::Print("Unable to set CA Publisher Min Payment due to missed publisher ID") and return undef) unless $publisher_id;

    my $payors = RPS::DB::Item::Payor->GetPayorsWithCAPublisherMinPayment();

    while ($payors->hasNext()) {
        my $payor = $payors->next;
        $self->{CAPublisherAccount} = RPS::Publisher::CA::PublisherAccount->new( publisherID => $publisher_id, payorID => $payor->{payor_id} );
        $self->{CAPublisherAccount}->{MinPayment} = $payor->{ca_publisher_min_payment};
        $self->{CAPublisherAccount}->save;
    }
}

###
1;    #
###

