#!/usr/bin/perl
#
# Report all importers ever used, a file imported, the number of times used
# and the top client and count.
#
# 1. Grab all unique Service ID version pairs from the client file tables where
#    the file does not have a parent id (is an import not a split)
# 2. Gather the importer information from RPS::Sale::File table;
# 3. Query each client database to find a sample file and the importer counts.
#
# Limitation:
#
#   Because the importer used is not stored in the database this must be pulled
#   from code.  Therefore any changes to service/version pairs in code will
#   alter this report.
#

use strict;

use Getopt::Std;
use File::Basename;

my %opt;
usage() unless getopts('c:qhldv', \%opt);

if( $opt{l} ) {
    list_clients( $ARGV[0] );
}

if( $opt{h} ) {
    usage();
}

my $controller = new ImporterSample( client_id    => $opt{c},
                                     filename     => $ARGV[0],
                                     quiet        => $opt{q},
                                     verbose      => $opt{v},
                                     debug        => $opt{d} );

$controller->run();

sub usage {
    my $prog = basename $0;

    print <<EofUSAGE;

usage: $prog [-c client_id] [-l client_name/pattern] [-h] [-d]
            -c - Client ID (if not specified then run for all clients)
            -l - List client ids (host pattern is optional)
            -d - display debug information to STDERR
            -v - display verbose debug information to STDERR
            -q - Do not output summary report
            -h - display this screen
EofUSAGE

exit 1;
}

sub list_clients {
    my $host = shift;
    my $key;
    foreach $key ( sort {$a <=> $b} keys( %Common::RSDB::CLIENT_DB ) ) {
        printf( "%-20s %-10s ID: %s\n",
                $Common::RSDB::CLIENT_DB{$key}->{db_name},
                "($Common::RSDB::CLIENT_DB{$key}->{host_id})",
                $key )
            if( ! defined($host) || $Common::RSDB::CLIENT_DB{$key}->{db_name} =~ /$host/i );
    }
    exit 1;
}

package DB::File;

use lib '/app/tools/raptor/lib';
use base 'Raptor::DB::Item::File';

use constant kTable => 'file';
use constant kDB => Common::DB::Item::kClientDB();

sub Get {
    my $class = shift;
    my %args = @_;
    my $dbo = Common::RSApp::GetClientDB();

    my $sql = "SELECT * FROM file " .
              "WHERE service_id = $args{service_id} AND " .
                    "version_num = $args{version_num} AND " .
                    "parent_file_id IS NULL " .
              "ORDER by date_processed DESC LIMIT 1";

    my $sth = $dbo->DoCmd($sql);
    return $sth->fetchrow_hashref;
}

sub GetServiceCount {
    my $class = shift;

    my $dbo = Common::RSApp::GetClientDB();
    my $sql = "SELECT service_id, version_num, count(*) as count " .
              "FROM file " .
              "WHERE service_id IS NOT NULL and version_num IS NOT NULL " .
              "GROUP BY service_id, version_num";

    return $dbo->DoCmd($sql);
}

1;

package ImporterSample;

use Data::Dumper;
use Sys::Hostname;

use lib '/app/tools/common/lib';
use Common::RSApp;
use Common::Util;
use Common::Assert;
use Common::WriteXML;


use lib '/app/tools/common/lib';
use Common::Client;
use base 'Common::Script';

use lib '/app/tools/support/lib';
use Support::Service::ServiceSimple;

use lib '/app/tools/rps/lib';
use RPS::Import::Service;

sub _init {
    my $self = shift;
    my %args = @_;
    $self->SUPER::_init(@_);

    my %clients;

    $self->{_filename} = $args{filename};

    return $self;
}

sub run_process
{
    my $self = shift;
    my $infile = $self->_getFileHandle($self->{_filename});
    my $i = 1;
    my @list;

    my $serviceData = $self->_getServiceData();

    print join( "\t", "Service", "Version", "Importer",
                      "File", "Physical Importer", "Physical Service", "Last Used", "Count", "Top Client", "Top Count" ) . "\n";

    foreach my $serviceID ( keys(%$serviceData) ) {
        foreach my $version ( keys( %{$serviceData->{$serviceID}} ) ) {
            my $importer = $self->_getImporter( $serviceID, $version );
            my $history  = $self->_getHistory( $serviceID, $version );

            print join( "\t", $self->_prettyService($serviceID),
                              $version, $importer,
                              $history->{file},
                              $self->_isPhysicalImporter( $importer ),
                              $self->_isPhysicalService( $serviceID ),
                              $history->{last},
                              $serviceData->{$serviceID}->{$version}->{count},
                              $self->_prettyClient($serviceData->{$serviceID}->{$version}->{topclient}),
                              $serviceData->{$serviceID}->{$version}->{topcount},
                              ) . "\n";
        }
    }
}

sub _prettyClient {
    my $self = shift;
    my $clientID = shift;

    my $singleton = new Common::RSApp( clientID => 0 );
    my $client = new Common::Client(clientID => $clientID);
    $singleton = undef;

    return $client->ClientName . " ($clientID)";
}

sub _prettyService {
    my $self = shift;
    my $serviceID = shift;

    my $service = new Support::Service::ServiceSimple(serviceID => $serviceID);

    my $name = $service->ServiceName ? $service->ServiceName : "undef";
    return "$name ($serviceID)";
}

sub _getFileHandle {
    my $self = shift;
    my $filename = shift || return *STDIN;

    open( INFILE, $filename ) || die "Can't read input file: $filename ($!)";
    return *INFILE;
}

sub _getServiceData {
    my $self = shift;
    my @list = $self->_get_client_list();

    foreach my $client ( @list ) {
        my $singleton = new Common::RSApp( clientID => $client );
        my $data = $self->_getClientServiceData( $client );
    }

    return $self->{_serviceData};
}

sub _getClientServiceData {
    my $self = shift;
    my $client = shift;
    my $clientID = Common::RSApp::GetClientID();

    my $data = $self->{_serviceData};

    my $sth = DB::File->GetServiceCount();

    while( my $row = $sth->fetchrow_hashref() ) {
        my $service = $row->{service_id};
        my $version = $row->{version_num};

        if( defined($service) && defined($version) ) {
            $data->{$service}->{$version}->{count} += $row->{count};

            if( $data->{$service}->{$version}->{topclient} ) {
                if($data->{$service}->{$version}->{topcount} < $row->{count}) {
                    $data->{$service}->{$version}->{topclient} = $clientID;
                    $data->{$service}->{$version}->{topcount}  = $row->{count};
                }
            } else {
                $data->{$service}->{$version}->{topclient} = $clientID;
                $data->{$service}->{$version}->{topcount}  = $row->{count};
            }
        }
    }

    $self->{_serviceData} = $data;

}


sub _getImporter {
    my $self = shift;
    my $serviceID = shift;
    my $version = shift;

    return unless( $serviceID && $version );

    my $importers = RPS::Import::Service::GetImporters($serviceID);
    return $importers->{$version};
}

sub _getHistory {
    my $self = shift;
    my $serviceID = shift;
    my $version = shift;
    my @list = $self->_get_client_list();

    my $history;

    return unless( $serviceID && $version );

    foreach my $client ( @list ) {
        my $singleton = new Common::RSApp( clientID => $client );

        my $tmp = $self->_getClientHistory( $serviceID, $version );
        next unless($tmp);

        if( $history ) {
            if( $history->{last} gt $tmp->{last} ) {
                $history = $tmp;
            }
        } else {
            $history = $tmp;
        }

        $singleton = undef;
    }

    return $history;
}

sub _getClientHistory {
    my $self = shift;
    my $serviceID = shift;
    my $version = shift;
    my $clientID = Common::RSApp::GetClientID();
    my $history;

    my $file = DB::File->Get( service_id => $serviceID, version_num => $version );

    if( $file ) {
        if( $file ) {
            $history->{client_id} = $clientID;
            $history->{file} = $file->{file_dir} . "/" . $file->{file_name};
            $history->{last} = $file->{date_processed};
        }
    }

    return $history;
}

sub _get_client_list {
     my $self = shift;
     my @list;

     my $host = hostname;
     $host =~ s/\..*//g;
     $self->debug( "Running on $host" );

     assert( $self );
     assert( $host );
     my $singleton = new Common::RSApp( clientID => 0 );

     return ($self->{_client_id}) if( defined($self->{_client_id}) );

     # If this is being run on a production box
     if( Common::RSApp::IsProductionServer ) {
         return sort { $a <=> $b } Common::RSDB::GetAllRPSClientIDs();
     }
     # Running on some other host, run of all install DBs on localhost
     else {
         return sort { $a <=> $b } Common::RSDB::GetLocalClientIDs( $host );
     }
}

sub _isPhysicalImporter {
    my $self = shift;
    my $importer = shift;

    my @physicalImporters = qw( RPS::Import::ADAPhys
                                RPS::Import::AmazonCreateSpace
                                RPS::Import::AmazonPhys
                                RPS::Import::BMG
                                RPS::Import::BMGCHouse
                                RPS::Import::BMGSony2
                                RPS::Import::BMGSonyPhys
                                RPS::Import::BMGSonyPhys2
                                RPS::Import::Caroline
                                RPS::Import::CreateSpace
                                RPS::Import::Dock
                                RPS::Import::DownloadCentric
                                RPS::Import::DTArtistDirect
                                RPS::Import::DTInternational
                                RPS::Import::DTThirdParty
                                RPS::Import::Echo
                                RPS::Import::Echospin
                                RPS::Import::Faithworks
                                RPS::Import::Fontana
                                RPS::Import::Fusion
                                RPS::Import::HarmoniaMundi
                                RPS::Import::KochEntCanada
                                RPS::Import::KochPhysArc
                                RPS::Import::LMMGSales
                                RPS::Import::LookoutDirect
                                RPS::Import::Navarre
                                RPS::Import::NugsRevised
                                RPS::Import::OutSideMusic
                                RPS::Import::ProperUK
                                RPS::Import::Red
                                RPS::Import::RevolverPhysical
                                RPS::Import::Rootsy
                                RPS::Import::RoughTradeDist
                                RPS::Import::RoughTradeDist2
                                RPS::Import::RSFormat
                                RPS::Import::RSFormatFull
                                RPS::Import::RSPhysicalFormat
                                RPS::Import::Rykodisc
                                RPS::Import::Rykodisc2
                                RPS::Import::SanctHistorical
                                RPS::Import::SDROutsideSales
                                RPS::Import::Shellshock
                                RPS::Import::TouchNGoPhys
                                RPS::Import::UniversalCAPhysical
                                RPS::Import::Welk );

    return grep( /^$importer$/, @physicalImporters ) ? "P" : "";
}

sub _isPhysicalService {
    my $self = shift;
    my $serviceID = shift || return;

    my @services = qw( 46 47 48 49 50 51 54 55 56 57 58 59 61 63 64 66 78 139
                       140 155 156 160 170 172 174 256 275 277 282 350 );

    return grep( /^$serviceID$/, @services ) ? "X" : "";
}

1;
