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


# This is the base class for all of our track licenses.
# There is a set of common columns that most flavors will have,
# and this class handles those.
# Note that you will never want to instantiate this directly.

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::DB::Item::ReserveLiquidation;
use RPS::DB::Item::FormDefaults;
use RPS::DB::Item::MechanicalStatementItem;
use RPS::DB::Item::RegionCountryMap;
use RPS::DB::Item::Product;
use RPS::License::LicenseType;

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

use constant kDateLowerLimit	=> '1900-01-01';
use constant kDateUpperLimit	=> '2050-12-31';


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

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

	my %properties;

    if ($args{_dbItem})
    {
        $self->_propertiesFromDBItem(\%properties, $args{_dbItem});
    }
    elsif ($args{trackLicenseID})
    {
        $self->_propertiesFromDB(\%properties, $args{trackLicenseID});
    }
    elsif($args{trackID})
    {
		$self->_propertiesFromDefaults(\%properties, trackID => $args{trackID},
								 	   licenseType => $args{licenseType},
								 	   controlledCompositionID => $args{controlledCompositionID});
	}
	else
	{
		# this shouldn't happen because you can't create a new TrackLicense
		# without knowing which track or controlledComp to link it with
		#
		assert(0);
	}

	$self->_initProperties(\%properties);

    return $self;
}


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

    my $dbItem = $self->_getDBItem($trackLicenseID);
	$self->_propertiesFromDBItem($hrProperties, $dbItem);
}


#sub _getDBItem
#{
#    my ($self, $id) = @_;
#
#    die "ERROR - You must override this method to instantiate the correct 'flavor' of DB Item";
#}


# this gets called after we update/insert so
# we can refresh our properties
sub _setPropertiesFromDBItem
{
	my ($self, $dbItem) = @_;

	my %properties;
	$self->_propertiesFromDBItem(\%properties, $dbItem);
	$self->_initProperties(\%properties);
}


# You are going to want to override this method to set up the key property.
# For example, if this is a Canadian track license, that might be 'ca_track_license_id'.
#
sub _propertiesFromDBItem
{
	my ($self, $hrProperties, $dbItem) = @_;

    # !!! Note that the _key_ field will need to be declared and set in the overridden method.
    #
#	$hrProperties->{track_license_id}			= $dbItem->track_license_id,


	$hrProperties->{track_id}					= $dbItem->track_id,
	$hrProperties->{type}						= $dbItem->type,
	$hrProperties->{share}						= $dbItem->share,
	$hrProperties->{payor_id}				    = $dbItem->payor_id,
	$hrProperties->{status}						= $dbItem->status,
	$hrProperties->{inactive}	                = $dbItem->inactive,
	$hrProperties->{date_sent}					= $dbItem->date_sent;
	$hrProperties->{date_received}				= $dbItem->date_received;
	$hrProperties->{date_issued}				= $dbItem->date_issued;
	$hrProperties->{lock_date}                  = $dbItem->lock_date;
	$hrProperties->{term_start}					= $dbItem->term_start;
	$hrProperties->{term_end}					= $dbItem->term_end;
	$hrProperties->{publisher_direct}			= $dbItem->publisher_direct;
	$hrProperties->{issuer_license_id}			= $dbItem->issuer_license_id;
    $hrProperties->{rate_basis}             	= $dbItem->rate_basis;
    $hrProperties->{rate_type}              	= $dbItem->rate_type;
    $hrProperties->{finance_account_id}     	= $dbItem->finance_account_id;
    $hrProperties->{reserve_percentage}     	= $dbItem->reserve_percentage;
    $hrProperties->{penny_rate}             	= $dbItem->penny_rate;
    $hrProperties->{product_type_id}        	= $dbItem->product_type_id;
    $hrProperties->{rate_percentage}     	    = $dbItem->rate_percentage;
    $hrProperties->{percentage_of_sales}  	    = $dbItem->percentage_of_sales;
    $hrProperties->{packaging_deduction}    	= $dbItem->packaging_deduction;
    $hrProperties->{free_goods}             	= $dbItem->free_goods;
    $hrProperties->{misc_deduction}         	= $dbItem->misc_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;
	$hrProperties->{region_id}                  = $dbItem->region_id,
	$hrProperties->{comments}	                = $dbItem->comments,
	$hrProperties->{cross_collateralized}	    = $dbItem->cross_collateralized,
	$hrProperties->{digital_reserves_enabled}	= $dbItem->digital_reserves_enabled,

	# from ControlledComp
	#
	$hrProperties->{controlled_composition_id}	= $dbItem->controlled_composition_id;
	$hrProperties->{rate_percentage}	        = $dbItem->rate_percentage;
}

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

	# pre-defined defaults
	#
    $hrProperties->{rate_percentage} = 100;
    $hrProperties->{percentage_of_sales} = 100;

    my $defaultPayor = RPS::DB::Item::Payor->GetDefault();
    $hrProperties->{payor_id} = $defaultPayor->payor_id;


	# trackID is required to create a new TrackLicense
	#
	my $trackID = $args{trackID};
    assert($trackID);
	$hrProperties->{track_id} = $trackID;


    # !!! Set the 'type' property in the subclass.
}


# !!! Will need to be overidden to set the Key property.
#
sub _initProperties
{
    my ($self, $props) = @_;

    # original TrackLicense
    #
#    $self->{TrackLicenseID}			= Common::FormObject::Scalar->new(value => $props->{track_license_id}, readOnly => 1);
    $self->{TrackID}				= Common::FormObject::Scalar->new(value => $props->{track_id}, required => 1);

    $self->{Type}					= Common::FormObject::Scalar->new(value => $props->{type}, required => 1);
    $self->{Share}					= Common::FormObject::Scalar::Percent->new(value => $props->{share}, precision => '4.2', minValue => 0.1, maxValue => 9999);
    $self->{Status}					= Common::FormObject::Scalar->new(value => $props->{status}, readOnly => 1);
    $self->{ParentTrackLicenseID}	= Common::FormObject::Scalar->new(value => $props->{parent_track_license_id});
    $self->{Inactive}	            = Common::FormObject::Scalar::Boolean->new(value => $props->{inactive});
    $self->{PayorID}	            = Common::FormObject::Scalar->new(value => $props->{payor_id});

    $self->{DateSent}				= Common::FormObject::Scalar::Date->new(value => $props->{date_sent});
    $self->{DateReceived}			= Common::FormObject::Scalar::Date->new(value => $props->{date_received});
    $self->{DateIssued}				= Common::FormObject::Scalar::Date->new(value => $props->{date_issued});
    $self->{LockDate}				= Common::FormObject::Scalar::Date->new(value => $props->{lock_date});
    $self->{TermStart}				= Common::FormObject::Scalar::Date->new(value => $props->{term_start});
    $self->{TermEnd}				= Common::FormObject::Scalar::Date->new(value => $props->{term_end});
    $self->{PublisherDirect}	   	= Common::FormObject::Scalar::Boolean->new(value => $props->{publisher_direct});
    $self->{IssuerLicenseID}	   	= Common::FormObject::Scalar::String->new(value => $props->{issuer_license_id}, maxlength => 40);
    $self->{DigitalReservesEnabled}	= Common::FormObject::Scalar::Boolean->new(value => $props->{digital_reserves_enabled});

    $self->{RegionID}	            = Common::FormObject::Scalar->new(value => $props->{region_id});
    $self->{Comments}	            = Common::FormObject::Scalar::String->new(value => $props->{comments});

    $self->{DateCreated}        	= Common::FormObject::Scalar::DateTime->new(value => $props->{date_created}, readOnly => 1);
    $self->{DateModified}       	= 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);

}

sub ReserveLiquidationList { shift->{ReserveLiquidationList} }

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

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

    return $valid if ($skipRequiredFields);

	if (! $self->PublisherID() && $self->Type() != RPS::License::LicenseType::kPublicDomain)
	{
		$self->{PublisherID}->setError(Common::FormObject::kErrFieldBlank);
		$valid = 0;
	}

	if( $self->DigitalReservesEnabled() && ! $self->ReservePercentage() ) {
		$self->{ReservePercentage}->setError(Common::FormObject::kErrRequiredFields);
		$valid = 0;
	}

	if (($self->Type() == RPS::License::LicenseType::kPublishingLicense) ||
	    ($self->Type() == RPS::License::LicenseType::kRingtone))
    {
    	my $sum = 0;
        if ($self->ReservePercentage() && $self->ReserveLiquidationList() )
        {
            foreach my $liq (@{$self->ReserveLiquidationList->getList()})
            {
                if(defined $liq && $liq->Percent())
                {
                    $sum += $liq->Percent();
                }
            }
            if ($sum == 0)
            {
    			$self->ReserveLiquidationList->setError(Common::FormObject::kErrFieldBlank);
    			$valid = 0;
    	    }
        }
    }


	return $valid;
}



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

	# original TrackLicense
	#
	$dbItem->track_id($self->TrackID());
	$dbItem->type($self->Type());
	$dbItem->share($self->Share());
    $dbItem->date_sent($self->DateSent());
    $dbItem->date_received($self->DateReceived());
    $dbItem->date_issued($self->DateIssued());
    $dbItem->lock_date($self->LockDate());
    $dbItem->term_start($self->TermStart());
    $dbItem->term_end($self->TermEnd());
    $dbItem->publisher_direct($self->PublisherDirect());
    $dbItem->issuer_license_id($self->IssuerLicenseID());
	$dbItem->inactive($self->Inactive());
	$dbItem->payor_id($self->PayorID());
    $dbItem->region_id($self->RegionID());
    $dbItem->digital_reserves_enabled($self->DigitalReservesEnabled());
}


# !!! Should we just mke the decision that, irregardless of what table we read the data from,
# the XML Key Property will _always_ be called 'TrackLicenseID'?  That would make life easier. (I think).

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

    # This will either return an existing item, or a new item, depending on whether
    # we have an ID yet.
    #
    return $self->_getDBItem($self->TrackLicenseID());
}

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

	my $dbItem = $self->_initSave();

	$self->_setDBValues($dbItem);

	$dbItem->save();

    $self->_setPropertiesFromDBItem($dbItem);

}


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

    # Using a somewhat more certain method now to tell when a track license has been used.
    #
    return undef if ($self->{InUse});

    my $dbItem = $self->_getDBItem($self->TrackLicenseID());
	$dbItem->delete();
}



# Need to handle PublisherID a little differently.
# I want to be automatically update the PublisherName field when this is changed.
# !!! But, Publishers are context-specific... So this needs to become more abstract.
#
sub PublisherID
{
    my ($self, @args) = @_;

    if ($self->{PublisherID})
    {
        my $rval = $self->{PublisherID}->access(@args);
        if (scalar @args && $rval)
        {
            my $pubID = $self->{PublisherID}->access();
            my $publisherName = '- Unknown -';
            if ($pubID)
            {
                my $pubObj = $self->_getPublisherObject($pubID);
            }

            # This field is read-only...  The 'best' way to deal with it is to
            # simply _replace_ the object.
            #
    	    $self->{PublisherName} = Common::FormObject::Scalar->new(value => $publisherName, readOnly => 1);
        }
        return $rval;
    }

}


sub _getPublisherObject
{
    my ($self, $pubID) = @_;

    # Override this to fetch the correct sort of publisher.
    #
    die "ERROR - You must override _getPublisherObject";
# Example:
#		    my $pubObj = RPS::Publisher::Publisher->new(publisherID => $pubID);
}


###
1;#
###
