#---------------------------------------------------------------
# ____                   _ _         ____  _
#|  _ \ ___  _   _  __ _| | |_ _   _/ ___|| |__   __ _ _ __ ___
#| |_) / _ \| | | |/ _` | | __| | | \___ \| '_ \ / _` | '__/ _ \
#|  _ < (_) | |_| | (_| | | |_| |_| |___) | | | | (_| | | |  __/
#|_| \_\___/ \__, |\__,_|_|\__|\__, |____/|_| |_|\__,_|_|  \___|
#            |___/             |___/
#
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
# $Id$
#---------------------------------------------------------------
package BookPub::Sale::Report::Exceptions;
use strict;
use warnings;

use File::Path;

use lib '/app/tools/common/lib';
use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::File;
use BookPub::DB::Item::Service;
use BookPub::Config;
use BookPub::DB::Item::Sale::AllExceptionsReport;
use Common::Util;
use Common::Assert;

use base 'BookPub::Sale::Report';

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

    return 'BookPub::Sale::Report::Exceptions::Row';
}

sub _seperator {
    my ($self) = @_;
    return "\t";
}

#sub fileName
#{
#    my ($self) = @_;
#    return 'AllExceptions.txt';
#}
#
#sub excelFileName
#{
#    my ($self) = @_;
#    return 'AllExceptions.xls';
#}

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

    if ( !$self->{_excelFilePath} ) {
        my $baseDir = $self->_baseDir();
        $self->{_excelFilePath} = $baseDir . '/' . $self->excelFileName();
    }
    return $self->{_excelFilePath};
}

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

    # Make sure we have a directory to write the final file into.
    #
    my $baseDir = $self->_baseDir();
    if ( !-d $baseDir ) {
        File::Path::mkpath($baseDir) || die "ERROR - make_path failed for $baseDir: $!";
    }

    my $dest_file_path = $self->filePath();
    my $tmp_file_path  = $dest_file_path . '-tmp';

    unless ( open TMP, ">$tmp_file_path" ) {
        die "can't create file $tmp_file_path\n";
    }
    binmode( TMP, ':utf8' );

    # !!! I'm joining 3 tables: file,sale,service.
    # Which DB::Item interface ought to own that?
    # !!! Let's try extending the 'Sale' table to include the extra rows.
    #
    my $sales = $self->_getSales();

    #    my $sales = BookPub::DB::Item::Sale::AllExceptionsReport->ReportQuery();

    my $rowClass = $self->getRowClass();
    my @all_rows = ();

    my $fields = $rowClass->Fields();
    my $header = join( $self->_seperator, @$fields );
    print TMP "$header\n";

    while ( my $sale = $sales->next() ) {
        my $rowObj = $rowClass->new( sale => $sale );

        my @values = ();
        foreach my $fieldName (@$fields) {
            my $value = $rowObj->{$fieldName};
            $value = '' unless defined $value;
            $value =~ s/\s/ /g;
            push @values, $value;
        }

        # Actually output the row.
        # Note that we determine which character to use as a delimeter via a private method.
        #
        print TMP join( $self->_seperator(), @values ) . "\n";

    }

    # now that we have all the rows (hrefs) in an array,
    # let's sort it and write the data to our file.

    close TMP;

    # Just rename the temp file, and we're done.
    #
    `mv $tmp_file_path $dest_file_path`;

    return 1;

}

sub createExcel {
}

###
1;    #
###

package BookPub::Sale::Report::Exceptions::Row;
use strict;
use warnings;

use lib '/app/tools/common/lib';
use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::Service;
use BookPub::DB::Item::File;
use BookPub::Config;
use BookPub::Catalog::Imprint;
use BookPub::Matcher::Product;
use Common::Util;
use Common::Assert;
use Common::RSApp;

sub new {
    my ( $class, %args ) = @_;

    my $self = bless {}, $class;
    return $self->_init(%args);
}

# This is a static class method! Invoke like so:
# BookPub::Sale::Report::Royalty::Row->Fields()
#
sub Fields {
    my ($class) = @_;

    my $appRamCache = Common::RSApp::GetRAMCache();

    if ( !$appRamCache->{$class}{Fields} ) {
        my @fields;

        # By using a second private method, we'll be able
        # to use inheritance - This provides a method that
        # subclasses can override or extend.
        #
        $class->_addFields( \@fields );

        $appRamCache->{$class}{Fields} = \@fields;
    }

    return $appRamCache->{$class}{Fields};
}

sub _addFields {
    my ( $self, $fieldArray ) = @_;

    # What we're doing here is determining:
    # - The field order,
    # - The column names (i.e. the header labels)
    # - The accessor method name to provide that data.
    #
    push @$fieldArray, 'file_name';
    push @$fieldArray, 'service';
    push @$fieldArray, 'sale_id';
    push @$fieldArray, 'file_id';
    push @$fieldArray, 'product_type';
    push @$fieldArray, 'format_type';
    push @$fieldArray, 'purchase_type';
    push @$fieldArray, 'date_begin';
    push @$fieldArray, 'date_end';
    push @$fieldArray, 'service_product_id';
    push @$fieldArray, 'client_product_id';
    push @$fieldArray, 'isbn13';
    push @$fieldArray, 'isbn10';
    push @$fieldArray, 'imprint';
    push @$fieldArray, 'title';
    push @$fieldArray, 'subtitle';
    push @$fieldArray, 'author';
    push @$fieldArray, 'units';
    push @$fieldArray, 'revenue';
    push @$fieldArray, 'currency_code';
    push @$fieldArray, 'conversion_rate';

    #    push @$fieldArray, 'revenue_usd'; # !!! the currency code needs to be set dynamically to client's base currency
    push @$fieldArray, 'line_num';
    push @$fieldArray, 'import_status';
}

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

    $self->{'file_name'}          = $self->_prettyFileName( $sale->file_id );
    $self->{'service'}            = $sale->service;
    $self->{'sale_id'}            = $sale->sale_id;
    $self->{'file_id'}            = $sale->file_id;
    $self->{'product_type'}       = $sale->product_type;
    $self->{'format_type'}        = $sale->format_type;
    $self->{'purchase_type'}      = $sale->purchase_type;
    $self->{'date_begin'}         = Common::Client::Current()->Locale()->formatDate( $sale->date_begin );
    $self->{'date_end'}           = Common::Client::Current()->Locale()->formatDate( $sale->date_end );
    $self->{'service_product_id'} = $sale->service_product_id;
    $self->{'client_product_id'}  = $sale->r_client_product_id;
    $self->{'isbn13'}             = $sale->r_isbn13;
    $self->{'isbn10'}             = $sale->r_isbn10;
    $self->{'imprint'}            = $sale->r_imprint;
    $self->{'title'}              = $sale->r_title;
    $self->{'subtitle'}           = $sale->r_subtitle;
    $self->{'author'}             = $sale->r_author;
    $self->{'units'}              = Common::Client::Current()->Locale()->formatNumber( $sale->units );
    $self->{'revenue'}            = Common::Client::Current()->Locale()->formatMoney( $sale->revenue );
    $self->{'currency_code'}      = $sale->currency_code;
    $self->{'conversion_rate'}    = Common::Client::Current()->Locale()->formatNumber( $sale->conversion_rate );

    #    push @$fieldArray, 'revenue_usd'; # !!! the currency code needs to be set dynamically to client's base currency
    $self->{'line_num'}      = Common::Client::Current()->Locale()->formatNumber( $sale->line_num );
    $self->{'import_status'} = $sale->import_status;

    return $self;
}

sub _prettyFileName {
    my ( $self, $fileID ) = @_;
    my $count    = BookPub::DB::Item::File->ChildCount($fileID);
    my $file     = BookPub::DB::Item::File->Lookup( file_id => $fileID );
    my $fileName = $file->orig_file_name;

    if ( $count != 0 || $file->generation != 0 ) {
        my $displayGeneration = $file->generation + 1;
        $fileName .= " (Sp" . $displayGeneration . ")";
    }

    return $fileName;
}

1;
