package BookPub::RDAS::Request::ProductPrice;

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

use lib '/app/tools/bookpub/lib';

use BookPub::Catalog::Product::Book;
use BookPub::Catalog::Book::WithAuthor;
use BookPub::Catalog::Book::Title;

use base 'BookPub::RDAS::Request';

sub GetRequestObject {
    my $class     = shift;
    my $serviceID = shift;
    my %args      = @_;

    my %classes = (
        BookPub::Tracker::Service::APPLE()        => BookPub::RDAS::Request::ProductPrice::Apple,
        BookPub::Tracker::Service::AMAZON()       => BookPub::RDAS::Request::ProductPrice::Amazon,
        BookPub::Tracker::Service::BARNES_NOBLE() => BookPub::RDAS::Request::ProductPrice::BarnesNoble,
        BookPub::Tracker::Service::BORDERS()      => BookPub::RDAS::Request::ProductPrice::Borders,
        BookPub::Tracker::Service::SONY()         => BookPub::RDAS::Request::ProductPrice::Sony,
        BookPub::Tracker::Service::GOOGLE()       => BookPub::RDAS::Request::ProductPrice::Google,
    );

    my $type = $classes{"$serviceID"};

    die "No object defined for service $serviceID" unless ($type);

    eval "use $type";
    die "$@" if ($@);

    return $type->new(%args);
}

sub _validOptions {
    return ( ( 'resetURL', 'nosave', 'productID', 'bookID', shift->SUPER::_validOptions() ) );
}

sub includePhysicalProducts { }

sub _init {
    my $self = shift;

    $self->SUPER::_init(@_);

    # Physical products
    if ( $self->productID ) {
        my $product = new BookPub::Catalog::Product::Book::WithFormat( productID => $self->productID );

        # We want to ignore some physical formats.  Specifically audio formats.
        if ( $self->_isIgnoredFormat( $product->ProductFormat ) ) {
            Log->info( "Ignoring product ID " . $self->productID . " based on format" );
            return;
        }

        # We want to ignore products that aren't published
        if ( !$product->isPublished() ) {
            Log->info( "Ignoring product ID " . $self->productID . " based on published status" );
            return;
        }
    }

    # Digital products
    if ( $self->bookID ) {
        if ( !$self->_hasPublishedProducts() ) {
            Log->info( "Ignoring book ID " . $self->bookID . " because it has no published products" );
            return;
        }
    }

    if ( $self->productID || $self->bookID ) {

        my $urlObject = $self->_getURLObject();
        $self->{_url} = $urlObject->GetURL( bookID => $self->bookID, productID => $self->productID );

        # If we used the book id to get the URL then store the product ID
        $self->{_productID} = $urlObject->productID() unless ( $self->productID );

        # Clear any alerts and monitor items for ebook products previously used
        if ( $self->bookID && $self->productID() ) {
            BookPub::DB::Item::ProductMonitorItem->ResolveItems(
                book_id            => $self->bookID,
                exclude_product_id => $self->productID,
                service_id         => $urlObject->serviceID
            );
            BookPub::DB::Item::ProductMonitorAlert->ResolveAlerts(
                book_id            => $self->bookID,
                exclude_product_id => $self->productID,
                service_id         => $urlObject->serviceID
            );
        }

        unless ( $self->{_url} ) {
            $self->fail( failure => "Unable to determine product page url" ) unless ( $self->{_url} );
            return;
        }
    }

    return $self;
}

sub _hasPublishedProducts {
    my $self = shift;
    return unless ( $self->bookID );

    my $urlObject = $self->_getURLObject() || die;

    my $collection =
      BookPub::DB::Item::BookProduct->GetAllWithLimit( bookID => $self->bookID, ebookOnly => 1, serviceID => $urlObject->serviceID );
    while ( my $dbItem = $collection->next() ) {
        my $product = new BookPub::Catalog::Product::Book( dbItem => $dbItem );
        if ( $product->isPublished() ) {
            return 1;
        } else {
            Log->info( "  --  Product ID " . $product->ProductID . " is not published. " );
        }
        return 1 if $product->isPublished();
    }

    return;
}

sub _isIgnoredFormat {
    my $self   = shift;
    my $format = shift;

    assert($format);
    my $type = $format->{BookFormatType};

    die unless ($type);

    return $type->{Description} =~ /audio/i;
}

sub fail {
    my $self = shift;
    return $self->SUPER::fail(@_) unless ( $self->nosave );
}

sub _getURLObject { die "must be overloaded" }

1;
