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

use strict;
use warnings;
use Data::Dumper;
use Carp;
use Date::Calc qw( Date_to_Days Decode_Date_US );

use lib '/app/tools/common/lib';
use Common::Assert;
use Common::Util qw(decodeDateMysql);
use Common::Log;

use lib '/app/tools/rps/lib';
use RPS::License::BaseLicense;
use RPS::License::RateBasis;
use RPS::License::RateType;
use RPS::DB::Item::RegionCountryMap;
use RPS::DB::Item::Product;
use RPS::DB::Item::ReserveLiquidation;
use RPS::DB::Item::ProductType;
use RPS::Finance::Account;

use Common::FormObject;
use base 'RPS::License::BaseLicense';

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

    $self->SUPER::_propertiesFromDefaults( $hrProperties, %args );
    $hrProperties->{type} = $self->_type();
}

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

    $self->SUPER::_initProperties($props);

    $self->{ProductTypeID}       = Common::FormObject::Scalar->new( value => $props->{product_type_id} );
    $self->{FinanceAccountID}    = Common::FormObject::Scalar->new( value => $props->{finance_account_id} );
    $self->{RateType}            = Common::FormObject::Scalar->new( value => $props->{rate_type}, required => 1 );
    $self->{RateBasis}           = Common::FormObject::Scalar->new( value => $props->{rate_basis} );
    $self->{ReservePercentage}   = Common::FormObject::Scalar::Percent->new( value => $props->{reserve_percentage} );
    $self->{PennyRate}           = Common::FormObject::Scalar::Decimal->new(
        value => $props->{penny_rate}, precision => '.4', minValue => '0.0001'
    );
    $self->{PercentageOfSales}   = Common::FormObject::Scalar::Percent->new(
        value => $props->{percentage_of_sales}, minValue => 1, required => 1
    );
    $self->{FreeGoods}           = Common::FormObject::Scalar::Percent->new( value => $props->{free_goods} );
    $self->{MiscDeduction}       = Common::FormObject::Scalar::Percent->new( value => $props->{misc_deduction} );
    $self->{CrossCollateralized} = Common::FormObject::Scalar::Boolean->new( value => $props->{cross_collateralized} );

    $self->{RatePercentage}      = Common::FormObject::Scalar::Percent->new( 
        value => $props->{rate_percentage}, minValue => '0.1', maxValue => 9999
    );

}

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

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

    return $valid if $skipRequiredFields;

    # 'rest of world' is not a valid region for a TrackLicense
    #
    if ( 0 == $self->RegionID() ) {
        Common::Log::Print("TrackLicense::validate - 0 is not a valid region id");
        $self->{RegionID}->setError(Common::FormObject::kErrFieldBlank);
        $valid = 0;
    }

    # If the product type is 'all' or 'digital album', the region must not contain any countries
    # other than US or Canada.
    # !!! This constraint may be just for US licences... But for now I will leave this here.
    #
    if (   !$self->ProductTypeID()
        || RPS::DB::Item::Product::kProductTypeDigital == $self->ProductTypeID()
        || RPS::DB::Item::Product::kProductTypeDigitalTrack == $self->ProductTypeID()
        || RPS::DB::Item::Product::kProductTypeRingtone == $self->ProductTypeID() ) {
        my $mapItems = RPS::DB::Item::RegionCountryMap->GetByRegionID( $self->RegionID() );
        while ( my $mapItem = $mapItems->next() ) {

            # !!! We ought to have these defined as constants someplace...
            # !!! The stuff in Const.pm is crap.
            #
            if ( 'US' ne $mapItem->country_code && 'CA' ne $mapItem->country_code ) {
                Common::Log::Print(
"TrackLicense::validate - attempting to use a region with a non us or ca country code on an all products or digital license"
                );
                $self->{RegionID}->setError(Common::FormObject::kErrFieldInvalid);
                $valid = 0;
                last;
            }
        }
    }

    # In any event, we can't use a region that contains a country that is already here.
    #
    # So, first, get all the region ids from licenses that have the same publisher,track, and product type.
    # !!! This will have to be overridden to account for TrackLicense types correctly.
    #
    my $countryCodeMap = $self->_getCountryCodeMapForValidation();

    # Make sure _our_ region doesn't have any of these countries in it.
    #
    my $ccMapItems = RPS::DB::Item::RegionCountryMap->GetByRegionID( $self->RegionID() );
    while ( my $mapItem = $ccMapItems->next() ) {
        if ( $countryCodeMap->{ $mapItem->country_code } ) {
            print STDERR "TrackLicense::validate - this track, publisher, payor, and product type is already licensed on country code "
              . $mapItem->country_code . "\n";
            $self->{RegionID}->setError(Common::FormObject::kErrFieldInvalid);
            $valid = 0;
            last;
        }
    }

    # Not going to allow penny rates of '0', or '0.000', or that sort of thing.
    #
    if ( RPS::License::RateType::kPenny == $self->RateType() ) {
        if ( !$self->PennyRate() ) {
            $self->{PennyRate}->setError(Common::FormObject::kErrFieldBlank);
            $valid = 0;
        } elsif ( $self->PennyRate() < 0.0001 ) {
            $self->{PennyRate}->setError(Common::FormObject::kErrFieldOutOfRange);
            $valid = 0;
        }
    }

    # RateBasis is only required if the rate type is not penny rate
    #
    if ( !$self->RateBasis() && $self->RateType() != RPS::License::RateType::kPenny ) {
        $self->{RateBasis}->setError(Common::FormObject::kErrFieldBlank);
        $valid = 0;
    }

    if ( RPS::License::RateBasis::kLock == $self->RateBasis() && !$self->LockDate() ) {
        $self->{LockDate}->setError(Common::FormObject::kErrFieldBlank);
        $valid = 0;
    }

    return $valid;
}

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

    $self->SUPER::_setDBValues($dbItem);

    $dbItem->product_type_id( $self->ProductTypeID() );
    $dbItem->rate_basis( $self->RateBasis() );
    $dbItem->rate_type( $self->RateType() );
    $dbItem->penny_rate( $self->PennyRate() );
    $dbItem->finance_account_id( $self->FinanceAccountID() );
    $dbItem->reserve_percentage( $self->ReservePercentage() );
    $dbItem->rate_percentage( $self->RatePercentage() );
    $dbItem->percentage_of_sales( $self->PercentageOfSales() );
    $dbItem->free_goods( $self->FreeGoods() );
    $dbItem->misc_deduction( $self->MiscDeduction() );
    $dbItem->cross_collateralized( $self->CrossCollateralized() );

    $dbItem->comments( $self->Comments() );
}

sub _getMatchingProductTypes {
    my $self = shift;
    my $productTypeID = shift || return;

    my $collection;

    if ( $productTypeID == RPS::DB::Item::ProductType::kAllPhysicalProducts ) {
        $collection = RPS::DB::Item::ProductType->GetAllPhysical();
    } elsif ( $productTypeID == RPS::DB::Item::ProductType::kAllDigitalProducts ) {
        $collection = RPS::DB::Item::ProductType->GetAllDigital();
    } else {
        return [$productTypeID];
    }

    my @result;

    while ( my $row = $collection->next() ) {
        push( @result, $row->product_type_id );
    }

    return @result ? \@result : undef;
}

###
1;    #
###
