#!/usr/bin/perl -w
#
# Examine asset files and update validation cache if the file has been
# modifued in the last n days. (n defaults to 7).
#

use strict;

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

use lib '/app/tools/metadata/lib';
use Metadata::Cache;

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

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

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

my $cacher = new AssetValidation(
    client_id    => $opt{c},
    report_email => $opt{r},
    error_email  => $opt{x},
    days         => $opt{n},
    quiet        => $opt{q},
    verbose      => $opt{v},
    debug        => $opt{d}
);

$cacher->run();

sub usage {
    my $prog = basename $0;

    print <<EofUSAGE;

usage: $prog [-c client_id] [-r report_email_address] [-x error_email_address] [-l client_name/pattern] [-h] [-d]
            -c - Client ID (if not specified then run for all clients)
            -n - Number of days to look back for modified files (default: 7)
            -r - Send summary report to this email instead of STDOUT
            -x - Send error report to this email instead of STDERR
            -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 AlbumDB;

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

use lib '/app/tools/rps/lib';
use base 'RPS::DB::Item::AlbumDistributionReady';

sub GetImageFileAlbumID {
    my $class = shift;
    my $media_file_id = shift || die "media_file_id required";

    my $sql = "SELECT album_id FROM album_file WHERE media_file_id = $media_file_id";

    my $dbo        = Common::RSApp::GetClientDB();
    my $sth        = $dbo->DoCmd($sql);
    my ($album_id) = $sth->fetchrow_array();

    return $album_id;
}

sub GetAudioFileAlbumID {
    my $class = shift;
    my $media_file_id = shift || die "media_file_id required";

    my $sql =
        "SELECT asset_id "
      . "FROM product_track_file "
      . "INNER JOIN product_track USING (product_track_id) "
      . "INNER JOIN product USING (product_id) "
      . "WHERE media_file_id = $media_file_id";

    my $dbo        = Common::RSApp::GetClientDB();
    my $sth        = $dbo->DoCmd($sql);
    my ($album_id) = $sth->fetchrow_array();

    return $album_id;
}

sub isImageValid {
    my $class = shift;
    my $album_id = shift || die "album_id required";

    my $sql = "SELECT image_valid FROM album_distribution_ready WHERE album_id = $album_id";

    #print STDERR "QUERY: $sql\n";
    my $dbo           = Common::RSApp::GetClientDB();
    my $sth           = $dbo->DoCmd($sql);
    my ($image_valid) = $sth->fetchrow_array();

    return $image_valid;
}

sub isAudioValid {
    my $class = shift;
    my $album_id = shift || die "album_id required";

    my $sql = "SELECT audio_valid FROM album_distribution_ready WHERE album_id = $album_id";

    my $dbo           = Common::RSApp::GetClientDB();
    my $sth           = $dbo->DoCmd($sql);
    my ($image_valid) = $sth->fetchrow_array();

    return $image_valid;
}

sub DeleteCache {
    my $class = shift;
    my $album_id = shift || die "album_id required";

    my $sql = "DELETE FROM album_distribution_ready WHERE album_id = $album_id";

    my $dbo = Common::RSApp::GetClientDB();
    my $sth = $dbo->DoCmd($sql);
}

package AssetValidation;

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 base 'Common::CronScript';

use lib '/app/tools/rps/lib';
use base 'RPS::Catalog::Album';
use RPS::DB::Item::Album;
use RPS::DB::Item::Product;

use Data::Dumper;

use constant DEFAULT_MODIFY_SEARCH => 7;
use constant MEDIA_PATH            => '/media';
use constant FIND                  => '/usr/bin/find';

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

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

    $self->{_days} = $args{days} || DEFAULT_MODIFY_SEARCH;

    return $self;
}

sub _process {
    my $self = shift;

    my @files = $self->_getModifiedFiles();
    my %albumsToRemove;
    my $id;

    foreach my $file (@files) {
        if ( $file =~ /^img/ ) {
            $id = $self->_updateImageCache($file);
        } elsif ( $file =~ /^audio/ ) {
            $id = $self->_updateAudioCache($file);
        } else {
            die "unknown file type $file";
        }

        $albumsToRemove{$id} = 1 if ($id);
    }

    foreach my $album_id ( keys(%albumsToRemove) ) {
        $self->debug("Clear cache for album_id $album_id");
        AlbumDB->DeleteCache($album_id);
    }

}

sub _getModifiedFiles {
    my $self = shift;
    my @result;
    my $client_id  = Common::RSApp::GetClientID();
    my $img_path   = MEDIA_PATH . "/img/$client_id";
    my $audio_path = MEDIA_PATH . "/audio/$client_id";

    my $cmd = "[ -d $img_path ] && cd " . MEDIA_PATH . " && " . FIND . " img/$client_id -mtime -$self->{_days} -type f;";

    $cmd .= "[ -d $audio_path ] && cd " . MEDIA_PATH . " && " . FIND . " audio/$client_id -mtime -$self->{_days} -type f;";

    $self->debug("Running Cmd: $cmd");

    open( IN, "$cmd |" ) || die "$!";

    while (<IN>) {
        chomp;
        push( @result, $_ );
    }

    return @result;
}

sub _updateImageCache {
    my $self = shift;
    my $file = shift;

    my @fileParts = split( /\//, $file );
    my $mediaFileID = $fileParts[5];

    my $album_id = AlbumDB->GetImageFileAlbumID($mediaFileID);

    if ($album_id) {
        unless ( AlbumDB->isImageValid($album_id) ) {
            return $album_id;
        }
    }

    return undef;
}

sub _updateAudioCache {
    my $self = shift;
    my $file = shift;

    my @fileParts = split( /\//, $file );
    my $mediaFileID = $fileParts[5];

    my $album_id = AlbumDB->GetAudioFileAlbumID($mediaFileID);

    if ($album_id) {
        unless ( AlbumDB->isAudioValid($album_id) ) {
            return $album_id;
        }
    }

    return undef;
}
