#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2010 RoyaltyShare, Inc.   All Rights Reserved
#---------------------------------------------------------------
package BookPub::Price::SalePriceException::Count;
use strict;
use warnings;

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

use Common::RSApp;
use Common::Util;
use Common::Assert;
use Common::FormObject;

use base 'Common::FormObject';

use constant kVarianceGroupSize => 25;
use constant kUnitsGroupSize    => 25;

sub _init {
    my $self = shift;
    my %args = @_;

    $self->_initProperties( $args{searchArgs} );

    return $self;
}

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

    $self->{Totals} = $self->_setCollectionSize($searchArgs);
    $self->{Groups} = $self->_setGroupCollectionSizes($searchArgs);

    return $self;
}

sub totalDisplayedExceptions {
    my $self = shift;
    return $self->{Totals}->{DisplayedExceptions};
}

sub _setGroupCollectionSizes {
    my $self       = shift;
    my $searchArgs = shift;
    my $size       = kVarianceGroupSize;

    my $orderBy = $searchArgs->{order_by};
    $orderBy = $orderBy->[0] if ( $orderBy && ref($orderBy) eq 'ARRAY' );

    if ( $orderBy eq 'variance' ) {
        return $self->_setGroupCollectionVariance($searchArgs);
    } elsif ( $orderBy eq 'SUM(sale.units)' ) {
        return $self->_setGroupCollectionUnits($searchArgs);
    } else {
        return $self->_setGroupCollection($searchArgs);
    }
}

sub _setGroupCollection {
    my $self       = shift;
    my $searchArgs = shift;
    my @totals;

    my $collection = BookPub::DB::Item::SalePriceExceptionSearch->SearchGroupCount(%$searchArgs) || return;

    while ( my $row = $collection->next ) {
        push( @totals, { Name => $row->{group_field}, Count => $row->{count} } );
    }

    return { Group => \@totals };
}

sub _setGroupCollectionVariance {
    my $self       = shift;
    my $searchArgs = shift;
    my @totals;
    my %values;

    my $size = kVarianceGroupSize;
    my $group;

    my $collection = BookPub::DB::Item::SalePriceExceptionSearch->SearchGroupCount(%$searchArgs) || return;

    while ( my $row = $collection->next ) {
        $group = $row->{group_field} && $row->{group_field} > 0 ? int( $row->{group_field} / $size ) + 1 : 0;

        $values{$group} = 0 unless ( defined( $values{$group} ) );
        $values{$group} += $row->{count};

    }

    foreach my $key ( keys(%values) ) {
        push( @totals, { Name => $key, Count => $values{$key} } );
    }

    return {
        GroupSize => $size,
        Group     => \@totals
    };
}

sub _setGroupCollectionUnits {
    my $self       = shift;
    my $searchArgs = shift;
    my @totals;
    my %values;

    my $size = kUnitsGroupSize;
    my $group;

    my $collection = BookPub::DB::Item::SalePriceExceptionSearch->SearchGroupCount(%$searchArgs) || return;

    while ( my $row = $collection->next ) {
        $group = $row->{group_field} && $row->{group_field} > 0 ? int( ( $row->{group_field} - 1 ) / $size ) + 1 : 0;

        $values{$group} = 0 unless ( defined( $values{$group} ) );
        $values{$group} += $row->{count};

    }

    foreach my $key ( keys(%values) ) {
        push( @totals, { Name => $key, Count => $values{$key} } );
    }

    return {
        GroupSize => $size,
        Group     => \@totals
    };
}

sub _setCollectionSize {
    my $self       = shift;
    my $searchArgs = shift;

    my $hideApproved = $searchArgs->{hide_approved};
    $searchArgs->{hide_approved} = undef;

    my $collection = BookPub::DB::Item::SalePriceExceptionSearch->SearchCount(%$searchArgs);
    my $dbItem     = $collection->next();

    my $total      = $dbItem ? $dbItem->{total}      : undef;
    my $unapproved = $dbItem ? $dbItem->{unapproved} : undef;

    if ( defined($total) && defined($unapproved) ) {
        return {
            TotalExceptions     => $total,
            TotalApproved       => $total - $unapproved,
            TotalUnapproved     => $unapproved,
            DisplayedExceptions => $hideApproved ? $unapproved : $total,
        };
    }

    return;
}

###
1;    #
###
