#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package RPS::ArtistContract::Term;

use strict;
use warnings;
use Carp;
use Data::Dumper;

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

use lib '/app/tools/rps/lib';
use RPS::DB::Item::NewArtistContract;
use RPS::DB::Item::NewArtistContractTerm;
use RPS::DB::Item::ContractTermSource;
use RPS::ArtistContract::ProductFormat;
use RPS::ArtistContract::ChannelList;
use RPS::Region::RegionList;
use RPS::DB::Item::ContractRateType;

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

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

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

    my %properties;

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

    $self->_initProperties( \%properties );
    $self->_initSubs( \%properties );

    return $self;
}

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

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

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

    $self->{_inDB} = 1;

    $hrProperties->{artist_contract_term_id} = $dbItem->artist_contract_term_id;
    $hrProperties->{artist_contract_id}      = $dbItem->artist_contract_id;
    $hrProperties->{priority}                = $dbItem->priority;
    $hrProperties->{contract_term_source_id} = $dbItem->contract_term_source_id;
    $hrProperties->{region_id}               = $dbItem->region_id;
    $hrProperties->{channel_id}              = $dbItem->channel_id;
    $hrProperties->{price_level_id}          = $dbItem->price_level_id;
    $hrProperties->{contract_rate_type_id}   = $dbItem->contract_rate_type_id;
    $hrProperties->{rate}                    = $dbItem->rate;
    $hrProperties->{rate_reduction}          = $dbItem->rate_reduction;
    $hrProperties->{percentage_of_sales}     = $dbItem->percentage_of_sales;
    $hrProperties->{packaging_deduction}     = $dbItem->packaging_deduction;
    $hrProperties->{free_goods_deduction}    = $dbItem->free_goods_deduction;

    $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 ) = @_;

    $self->{ArtistContractTermID} = Common::FormObject::Scalar->new( value => $props->{artist_contract_term_id}, readOnly => 1 );
    $self->{ArtistContractID}     = Common::FormObject::Scalar->new( value => $props->{artist_contract_id} );
    $self->{Priority}             = Common::FormObject::Scalar->new( value => $props->{priority}, required => 1 );
    $self->{ContractTermSourceID} = Common::FormObject::Scalar->new( value => $props->{contract_term_source_id}, required => 1 );
    $self->{RegionID}             = Common::FormObject::Scalar->new( value => $props->{region_id}, required => 1 );
    $self->{ChannelID}            = Common::FormObject::Scalar->new( value => $props->{channel_id} );
    $self->{PriceLevelID}         = Common::FormObject::Scalar->new( value => $props->{price_level_id} );
    $self->{ContractRateTypeID}   = Common::FormObject::Scalar->new( value => $props->{contract_rate_type_id}, required => 1 );

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

    # We're going to force some values if the non-payable rate type has been selected.

    my ( $rate, $rateReduction, $percentageOfSales, $packagingDeduction, $freeGoods );

    if ( $props->{contract_rate_type_id} == RPS::DB::Item::ContractRateType::kRateTypeNonPayable() ) {
        $rate               = 0;
        $rateReduction      = 100;
        $percentageOfSales  = 100;
        $packagingDeduction = 0;
        $freeGoods          = 0;
    } else {
        $rate               = $props->{rate};
        $rateReduction      = $props->{rate_reduction};
        $percentageOfSales  = $props->{percentage_of_sales};
        $packagingDeduction = $props->{packaging_deduction};
        $freeGoods          = $props->{free_goods_deduction};
    }

    $self->{Rate}          = Common::FormObject::Scalar::Decimal->new( value => $rate,          precision => '.4' );
    $self->{RateReduction} = Common::FormObject::Scalar::Percent->new( value => $rateReduction, maxValue  => 300 );
    $self->{PercentageOfSales}  = Common::FormObject::Scalar::Percent->new( value => $percentageOfSales );
    $self->{PackagingDeduction} = Common::FormObject::Scalar::Percent->new( value => $packagingDeduction );
    $self->{FreeGoodsDeduction} = Common::FormObject::Scalar::Percent->new( value => $freeGoods );

    # this is how the template tells the backend to delete one of these.
    # the default is 'OFF' (ie. don't delete)
    #
    $self->{Delete} = Common::FormObject::Scalar::Boolean->new();
}

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

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

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

    if ( $self->Delete() ) {
        if ( $self->hasDependency() ) {
            $self->{Delete}->setError('has_dependency');
            return 0;
        }

        # else, no need to validate any properties
        return 1;
    }

    foreach my $field (
        qw(ContractTermSourceID RegionID ChannelID PriceLevelID ContractRateTypeID Rate RateReduction PercentageOfSales PackagingDeduction FreeGoodsDeduction)
      ) {
        if ( $self->$field() ) {
            $self->{_hasData} = 1;
        }
    }

    if ( $self->{_hasData} ) {
        my $valid = $self->SUPER::validate();

        # contract term source is always required
        if ( !defined $self->ContractTermSourceID() ) {
            $self->{ContractTermSourceID}->setError(Common::FormObject::kErrFieldBlank);
            $valid = 0;
        } else {

            # Rate is required unless the non-payable rate type has been selected.
            #
            if ( $self->ContractRateTypeID() != RPS::DB::Item::ContractRateType::kRateTypeNonPayable() ) {
                if ( !defined $self->Rate() ) {
                    $self->{Rate}->setError(Common::FormObject::kErrFieldBlank);
                    $valid = 0;
                }
            }

            # only physical products need a channel and price level
            #
            if ( $self->_isPhysical() ) {
                if ( !defined $self->ChannelID() ) {
                    $self->{ChannelID}->setError(Common::FormObject::kErrFieldBlank);
                    $valid = 0;
                }
                if ( !defined $self->PriceLevelID() ) {
                    $self->{PriceLevelID}->setError(Common::FormObject::kErrFieldBlank);
                    $valid = 0;
                }
            }

            # terms with the following digital sources must have a rate type of % net revenue
            #
            #			if($self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceVPD() ||
            #	           $self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalStream() ||
            #	           $self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalTethered())
            #	           #$self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalAlbumPremium() ||
            #	           #$self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalTrackPremium() ||
            #	           #$self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalAlbumUpgrade() ||
            #	           #$self->IncomeSourceID() == RPS::DB::Item::IncomeSource::kIncomeSourceDigitalTrackUpgrade())
            #			{
            #				if(($self->ContractRateTypeID() != RPS::DB::Item::ContractRateType::kRateTypePercentRevenue()) &&
            #				   ($self->ContractRateTypeID() != RPS::DB::Item::ContractRateType::kRateTypeNonPayable()))
            #				{
            #					$self->{ContractRateTypeID}->setError(Common::FormObject::kErrFieldInvalid);
            #	    			$valid = 0;
            #				}
            #			}

        }

        return $valid;
    } else {
        return 1;
    }
}

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

    my $hasDigital = RPS::DB::Item::ContractTermSource->hasDigital( $self->ContractTermSourceID() );
    return $hasDigital ? undef : 1;
}

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

    if ( $self->Delete() ) {
        $self->delete();
        return;
    }

    return unless $self->{_hasData};

    my $dbObj;
    if ( $self->ArtistContractTermID() ) {
        $dbObj = RPS::DB::Item::NewArtistContractTerm->Lookup( artist_contract_term_id => $self->ArtistContractTermID() );
    } else {
        $dbObj = RPS::DB::Item::NewArtistContractTerm->Create();
    }

    # set fields here
    #
    $dbObj->artist_contract_id( $self->ArtistContractID() );
    $dbObj->priority( $self->Priority() );
    $dbObj->contract_term_source_id( $self->ContractTermSourceID() );
    $dbObj->region_id( $self->RegionID() );
    $dbObj->channel_id( $self->ChannelID() );
    $dbObj->price_level_id( $self->PriceLevelID() );
    $dbObj->contract_rate_type_id( $self->ContractRateTypeID() );
    $dbObj->rate( $self->Rate() );
    $dbObj->modified_by( $self->ModifiedBy() );
    $dbObj->date_modified(Common::DB::Item::kDateTimeNow);

    # rate_reduction and percentage_of_sales need to default to 100, not 0.
    #
    $dbObj->rate_reduction( $self->RateReduction() > 0          ? $self->RateReduction()     : 100 );
    $dbObj->percentage_of_sales( $self->PercentageOfSales() > 0 ? $self->PercentageOfSales() : 100 );

    $dbObj->packaging_deduction( $self->PackagingDeduction() );
    $dbObj->free_goods_deduction( $self->FreeGoodsDeduction() );

    # a little massaging of the data,
    # if we change a physical term to a digital then we need
    # to blank out certain fields that don't apply to digital
    #
    if ( !$self->_isPhysical() ) {
        $dbObj->channel_id(undef);
        $dbObj->price_level_id(undef);
    }

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

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

sub setDependency {
    my $self = shift;
    $self->{HasDependency} = 1;
}

sub hasDependency {
    my $self = shift;
    return $self->{HasDependency} ? 1 : 0;
}

sub delete {
    my $self = shift;

    if ( $self->{_inDB} ) {
        my $myDBObj = RPS::DB::Item::NewArtistContractTerm->Lookup( artist_contract_term_id => $self->ArtistContractTermID() );
        $myDBObj->delete();
    }
    return 1;
}

###
1;    #
###
