#------------------------------------------------------------
# Copyright (C) 2009 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package BookPub::Tracker::Command::Upload;
use strict;
use warnings;
use Data::Dumper;

use lib '/app/tools/common/lib';
use RSApache::Response::XSLT;
use RSApache::Response::Download;
use Common::Assert;
use RSApache::Message;

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::File;
use BookPub::Sale::File;
use BookPub::Tracker::Job::ImportSalesFile;

use lib '/app/tools/appuser/lib';
use AppUser::DB::Item::AccessLevel;

use BookPub::Tracker::Command::Main;

use base 'BookPub::Command';

sub cmd      { return "upload"; }
sub area     { return "tracker"; }
sub pageName { return 'Revenue File Upload'; }

# Request to block upload based on extension in case 10724
use constant kInvalidFileExtensions => qw( pdf jpg doc docx xml zip );

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

    # Give any inherited methods the first crack at this.
    # (This checks for login and basic access permissions).
    #
    my $response = $self->SUPER::execute();
    return $response if $response;

    my @lightweight_fh = $self->getCGI()->upload('fileUpload');

    my %newParams;
    my $messages;

    foreach my $fh (@lightweight_fh) {
        if ( defined $fh ) {
            my $newFileID;

            eval { $newFileID = $self->uploadFile($fh); };

            if ($@) {

                # If this was an ErrorMessage exception, add the message to the redirect.
                # Otherwise, re-throw it.
                #
                if ( ref $@ && $@->isa('RSApache::Message') ) {
                    my $message = $@;
                    $messages .= $message->toString() . "||";
                } else {
                    die $@;
                }
            }

            if ($newFileID) {

                # Queue up the import job
                #
                my $jobArgs = BookPub::Tracker::Job::ImportSalesFile->new( fileID => $newFileID );
                my $job = $jobArgs->enqueue();
            }
        }
    }

    if ($messages) {
        $newParams{rejected} = $messages;
    }

    # No matter what happened, we'll redirect back to the main page.
    #
    my $command = BookPub::Tracker::Command::Main->new(%newParams);
    return RSApache::Response::Redirect->new( $command->getRedirect() );
}

sub uploadFile {
    my ( $self, $fh ) = @_;

    my @invalidExtensions = kInvalidFileExtensions;

    my $orig_file_name = $fh;
    $orig_file_name =~ s/.*[\/\\](.*)/$1/;

    my $ext = lc $orig_file_name;
    $ext =~ s/.*\.//;

    # Examine the first two bytes in the file to see if it's an excel file.
    #
    my ( $fileData, $is_text, $is_excel, $is_excel_xml, $is_unsupported_excel, $is_utf8, $is_utf16, $is_zip );
    $is_text              = 0;
    $is_excel             = 0;
    $is_excel_xml         = 0;
    $is_utf16             = 0;
    $is_utf8              = 0;
    $is_unsupported_excel = 0;
    $is_zip               = 0;
    read( $fh, $fileData, 2, 0 );

    foreach ( split( //, $fileData ) ) {
        print STDERR "X>" . $_ . "<>" . ord($_) . "<>" . sprintf( "%02x", ord($_) ) . "<X\n";
        $is_excel++             if ( sprintf( "%02x", ord($_) ) eq "d0" );
        $is_excel++             if ( sprintf( "%02x", ord($_) ) eq "cf" );
        $is_unsupported_excel++ if ( sprintf( "%02x", ord($_) ) eq "09" );
        $is_text++  if ( sprintf( "%02x", ord($_) ) =~ /(\d\d)/ && sprintf( "%02x", ord($_) ) != 50 || sprintf( "%02x", ord($_) ) =~ /4d|6d|6f/ );
        $is_text++  if ( sprintf( "%02x", ord($_) ) =~ /(3b|2c)/i); # CSV files starting with ',' or ';' chars
        $is_utf16++ if ( sprintf( "%02x", ord($_) ) =~ /(ff|fe)/i );
        $is_utf8++  if ( sprintf( "%02x", ord($_) ) =~ /(ef|bb)/i );
        $is_zip++ if ( sprintf( "%02x", ord($_) ) =~ /(50|4b)/i && $ext =~ 'xls|xslm' );
        $is_excel_xml++ if ( sprintf( "%02x", ord($_) ) =~ /^(3c|3f)$/i && $ext eq 'xls' );
        print STDERR "X>" . $is_zip . "<X\n";
    }
    seek( $fh, 0, 0 );

    $is_excel_xml++ if ( $fh =~ /xlsx$/i );

    # !!! message XML...  I want to change this a bit.
    # Request to block upload based on extension in case 10724
    if ( $is_zip < 2 && $is_excel_xml < 1 && $is_excel < 2 && $is_utf16++ < 2 && $is_utf8 < 2 && $is_text < 1 || grep /^$ext$/,
        @invalidExtensions ) {
        die RSApache::Message->new( type => "error", code => "$orig_file_name|not_text_or_excel_or_excel_xml_workbook" );
    }

    # NOW we'll try to re-save a file using external library (FB21991)
    #if ( $is_unsupported_excel > 0 ) {
    #    die RSApache::Message->new( type => "error", code => "$orig_file_name|unsupported_excel_format" );
    #}

    if ( eof $fh ) {
        die RSApache::Message->new( type => "error", code => "$orig_file_name|empty" );
    }

    # this lets us reset the file handle
    my $start_of_file = tell($fh);

    # -------------------------

    # get md5sum and check for duplicate file
    my $md5_sum = Common::Util::md5sum($fh);
    if ( !defined $md5_sum ) {
        die RSApache::Message->new( type => "error", code => "$orig_file_name|unreadable" );
    }

    # reset the file handle to the start of the file
    seek( $fh, $start_of_file, 0 );

    # See if we already have a file with this name...
    #
    if ( BookPub::DB::Item::File->GetByMD5($md5_sum) ) {
        die RSApache::Message->new( type => "error", code => "$orig_file_name|duplicate" );
    }

    # -------------------------

    my $sf          = BookPub::Sale::File->new();
    my $new_file_id = $sf->SimpleUploadFromWeb(
        fh                => $fh,
        filename          => $orig_file_name,
        period_id         => 0,
        md5_sum           => $md5_sum,
        user_id           => $self->_getUser()->UserID(),
        unsupported_excel => $is_unsupported_excel,
    );

    if ($new_file_id) {
        return $new_file_id;
    } else {
        die RSApache::Message->new( type => 'error', code => "$orig_file_name|file_upload_saveerror $! $@" );
    }
}

1;
