#------------------------------------------------------------
# Copyright (C) 2006 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package BookPub::SearchCommand;

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

use lib '/app/tools/appuser/lib';
use lib '/app/tools/rps/lib';
use RPS::Pagination;

use lib '/app/tools/bookpub/lib';
use base 'BookPub::Command';

use constant kDefaultPageSize => 30;

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

    # Give any inherited methods the first crack at this.
    # (This checks for login and basic access permissions).
    #
    my $response = $self->SUPER::execute();
    return $response if $response;

    my $dbClass  = $args{dbClass};
    my $xmlClass = $args{xmlClass};
    my $xmlTag   = $args{xmlTag};
    my $pageSize = $self->getParam("PageSize") || $args{pageSize} || kDefaultPageSize;
    my $query    = $self->{query} || $self->getParam('Query');

    assert($xmlTag);
    assert($xmlClass);
    eval "require $xmlClass";

    # let them pass in a collection of their own
    #
    my $collection;
    if ( $args{collection} ) {
        $collection = $args{collection};
    } else {
        assert( $dbClass, "Missing required dbClass arg" );
        eval "require $dbClass";

        if ($query) {

            # Strip leading and trailing white space
            $query =~ s/^\s+//g;
            $query =~ s/\s+$//g;

            # if(validSearchTerm($searchParam))
            my $searchMethod = 'Search';
            if ( $args{searchMethod} ) {
                $searchMethod = $args{searchMethod};
            }
            if (1) {
                $collection = $dbClass->$searchMethod($query);
            } else {

                # TODO: not sure how to handle this
            }
        } else {
            my $getAllMethod = 'GetAll';
            if ( $args{getAllMethod} ) {
                $getAllMethod = $args{getAllMethod};
            }
            $collection = $dbClass->$getAllMethod();

            #            $collection = $dbClass->GetAll();
        }

    }

    if ( defined $collection ) {
        assert( $xmlClass, "Missing required xmlClass arg" );
        eval "require $xmlClass";

        # the new way to do this is to set the pagination parameters on the collection,
        # then we can create the pagination object by referencing the "totalSize()" of the collection.
        # By setting the pagination parameters in the collection before referencing any of its
        # internal properties we save it from doing a "select * from"
        #
        if ( $self->getParam("Page") ) {
            $collection->setPagination( pageIndex => $self->getParam("Page"), pageSize => $pageSize );
        } else {
            my $recordIndex = $self->getParam("Record") || 1;
            $collection->setPagination( recordIndex => $recordIndex, pageSize => $pageSize );
        }

        # the pagination occurs internally in the collection object
        #
        my @records;

        Common::Log::Debug($collection);
        while ( $collection->hasNext() ) {
            my $data = $collection->next();
            push @records, $xmlClass->new( dbItem => $data );
        }

        $self->{xml}{$xmlTag} = \@records if (@records);
        $self->{xml}{Pagination} = RPS::Pagination->new(
            total     => $self->_getCollectionSize($collection),
            recordNum => $collection->{_record},
            pageSize  => $pageSize
        );
    }

    return undef;
}

sub _getCollectionSize {
    my $self       = shift;
    my $collection = shift;

    return $collection->totalSize();
}

sub totalCount {
    my $self = shift;

    if ( $self->{xml}->{Pagination} ) {
        return $self->{xml}->{Pagination}->Total;
    } else {
        return 0;
    }
}

sub validSearchTerm {
    my $term = shift;

    # I think it's safe to require at least 3
    # alphanumeric characters
    #
    my $alphaTerm;
    ( $alphaTerm = $term ) =~ s/[^a-zA-Z0-9]//g;
    return 0 if ( length($alphaTerm) < 3 );

    return 1;
}

sub setPagesize {
    my $self = shift;

    # Check if the page size was passed in
    my $pagesize = $self->getParam( $self->pageSizeParamName() );

    # If not see if a cookie exists
    $pagesize = Common::Preference::GetValue( $self->pageSizePrefName() )
      unless ($pagesize);

    # Finally set it to the default
    $pagesize = $self->defaultPageSize() unless ($pagesize);

    # Now set the new page size preference
    my $setMethod = $self->pageSizeMethod();
    &$setMethod( $self->pageSizePrefName(), $pagesize );

    return $pagesize;
}

#
# Overloadable constants for defining the search page preferences
#
sub defaultPageSize   { 25 }
sub pageSizeParamName { 'PageSize' }
sub pageSizePrefName  { 'pagesize' }
sub pageSizeMethod    { 'Common::Preference::SetPersistentCookie' }

###
1;    # Play nicely.
###
