package Distribution::Packager::Napster;

use strict;

use Distribution::Util;

use Data::Dumper;
use File::Basename;

use Common::Assert;

use lib '/app/tools/distribution/lib';
use base 'Distribution::PackagerNew';

sub _requireAllowed { 1 }

#sub _xsdFile { 'myspace-v2.xsd' }

sub _imageFormat {
    {
        geometry => '1080x1080',
        density  => 72,
    };
}

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

    my $type     = $args{type};
    my $filename = $args{filename};
    my $package  = $args{converter} || $self->_audioConverter( $args{type} );
    my $options  = $args{options} || $self->_audioConverterOptions( $args{type} );

    eval "require $package";
    die "Failed to load converter: $@" if ($@);

    my $args = $options ? $options : {};
    my $obj = $package->new( filename => $filename, %$args );

    if ( !$obj || $obj->error() ) {
        $self->_processFailure( $obj->error(), 15 );
    }

    return $obj;
}

sub _audioConverter {
    my $self = shift;
    my $type = shift || '012';

    return $type eq '012'
      ? 'MediaServe::Audio::Converter::MP3'
      : 'MediaServe::Audio::Converter::WMA';
}

sub _audioConverterOptions {
    my $self = shift;
    my $type = shift || '012';

    if    ( $type eq '001' ) { return { bitrate => 20,  frequency => 22 } }
    elsif ( $type eq '002' ) { return { bitrate => 32,  frequency => 32 } }
    elsif ( $type eq '007' ) { return { bitrate => 128, frequency => 44 } }
    elsif ( $type eq '008' ) { return { bitrate => 192, frequency => 44 } }
    elsif ( $type eq '012' ) { return { bitrate => 256 } }
    else                     { return {} }
}

sub _templateFile { 'napster.tt' }

sub _worldWideTerritory { 'WWD' }

###
#   File Structure
###
sub _createDistributionPackageName {
    my $self     = shift;
    my %args     = @_;
    my $format   = $args{format} || "%d%02d%02d_%02d%02d%02d";
    my $vendorID = $self->{_acctInfo}->Code() || die;

    return sprintf( '%s%0X', $vendorID, time() );
}

sub _localAlbumPath {
    my $self  = shift;
    my $album = shift;

    return $self->_localDistributionPath;
}

sub _localAudioFilePath {
    my $self   = shift;
    my $album  = shift;
    my $volume = shift;
    my $track  = shift;
    my $type   = shift || '012';
    my $code   = $type eq '012' ? 'mp3' : 'wma';

    my $dir = $self->_localAlbumPath($album) . "/audio/$code";
    mkdir_local($dir);

    return "$dir/" . $self->_albumAudioFileName( $album, $volume, $track, $type );
}

sub _localMetadataPath {
    my $self  = shift;
    my $album = shift;

    my $dir = $self->_localAlbumPath($album) . "/xml";
    mkdir_local($dir);

    return "$dir/" . $self->_albumMetadataName($album);
}

sub _localImagePath {
    my $self  = shift;
    my $album = shift;

    my $dir = $self->_localAlbumPath($album) . "/graphics";
    mkdir_local($dir);

    return "$dir/" . $self->_albumImageName($album);
}

sub _albumImageName {
    my $self     = shift;
    my $album    = shift;
    my $vendorID = $self->{_acctInfo}->Code() || die;

    return "${vendorID}_" . $album->{upc} . "_001." . $self->_albumImageExtension($album);
}

sub _albumMetadataName {
    shift->_distributionPackageName() . ".xml";
}

sub _albumAudioFileName {
    my $self     = shift;
    my $album    = shift;
    my $volume   = shift;
    my $track    = shift;
    my $type     = shift || '012';
    my $vendorID = $self->{_acctInfo}->Code() || die;
    my $format   = "${vendorID}_%s_%03d_%03d_$type.%s";

    return sprintf( $format, $album->{upc}, $volume->{sequence}, $track->{sequence}, $self->_albumAudioFileExtension($type) );
}

sub _albumAudioFileExtension {
    my $self = shift;
    my $type = shift || '012';
    return $self->_audioConverterObject( type => $type )->Extension();
}

###
#   Audio Conversion
###
sub _processAudio {
    my $self = shift;
    my ( $album, $volume, $track ) = @_;

    my $imagePrefix = $self->_albumImageName($album);
    $imagePrefix =~ s/_\d{3}\..*$//;

    $album->{'image-prefix'} = $imagePrefix;

    return $self->SUPER::_processAudio(@_);
}

sub _processTrack {
    my $self = shift;
    my ( $album, $volume, $track ) = @_;

    my $audioPrefix = $self->_albumAudioFileName( $album, $volume, $track );
    $audioPrefix =~ s/_\d{3}\..*$//;

    $track->{'audio-prefix'} = $audioPrefix;

    foreach my $audioType (qw( 001 002 007 008 )) {
        return unless ( $self->_convertAudio( @_, $audioType ) );
    }

    return $self->SUPER::_processTrack(@_);
}

###  Needed to create a preview file
sub _convertAudio {
    my $self = shift;
    my ( $album, $volume, $track, $type ) = @_;

    my $originalAudioPath = $self->_localOriginalAudioPath( $album, $volume, $track, $type );
    my $resultAudioPath = $self->_localAudioFilePath( $album, $volume, $track, $type );
    my $basePath = $self->_localBasePath();

    my $converter = $self->_audioConverterObject( filename => $originalAudioPath, type => $type );

    Common::Log::Debug("*** Converting Audio ***");
    Common::Log::Debug(" - AUDIO ORIG: $originalAudioPath");
    Common::Log::Debug(" - AUDIO DEST: $resultAudioPath");
    Common::Log::Debug( " - OBJ : " . ref($converter) );

    unless ( $converter->write($resultAudioPath) ) {
        $self->_processFailure( "Failed to convert audio: " . $converter->error(), 16 );
    }

    $track->{"audio-$type-path"} = $resultAudioPath;
    $track->{"audio-$type-path"} =~ s/$basePath\/?//;
    $track->{"audio-$type-filename"} = basename($resultAudioPath);

    $track->{"audio-$type-checksum"} = $self->_get_file_checksum($resultAudioPath);
    $track->{"audio-$type-size"}     = $self->_get_file_size($resultAudioPath);
    $track->{"audio-$type-duration"} = $self->_getFLACDuration($originalAudioPath);

    unless ( -e $resultAudioPath ) {
        print STDERR "Failed to convert audio type ($type): $resultAudioPath\n";
        return 0;
    }

    $self->_addToChecksum( $resultAudioPath, $track->{"audio-$type-checksum"} );

    return 1;
}

###
#   Metadata Handling
###
sub _prePackage {
    my $self = shift;
    my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime( $self->{_timestamp} );

    my $metadataFile = $self->_localMetadataPath();

    my $vendorID     = $self->{_acctInfo}->Code() || die;
    my $deliveryName = $self->_distributionPackageName();
    my $deliveryDate = sprintf( "%04d%02d%02d", $year + 1900, $mon + 1, $mday );

    my $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<delivery>
   <delivery-info>
      <distributor-name>$vendorID</distributor-name>
      <delivery-name>$deliveryName</delivery-name>
      <delivery-date>$deliveryDate</delivery-date>
   </delivery-info>\n";

    $self->_writeFile( $metadataFile, $xml );

    return $self->SUPER::_prePackage(@_);
}

sub _postPackage {
    my $self         = shift;
    my $metadataFile = $self->_localMetadataPath();

    $self->_writeFile( $metadataFile, "</delivery>\n" );

    return unless ( $self->_validateMetadata( $metadataFile, 1 ) );

    return $self->SUPER::_postPackage(@_);
}

sub _validateMetadata {
    my $self         = shift;
    my $metadataFile = shift || return undef;
    my $complete     = shift;

    return 1 unless ($complete);

    return $self->SUPER::_validateMetadata($metadataFile);
}

1;
