#!/usr/bin/perl
use strict;
use warnings;
use English;
use SOAP::Lite; # +trace => [qw/all -objects/];
use MIME::Base64 qw( encode_base64 );
use File::Basename;
use File::Type;
use Term::ReadPassword;
use IO::Compress::Zip qw( zip $ZipError );
use IO::File;
use IO::Prompt::Tiny qw( prompt );

my $soap = SOAP::Lite
    ->uri('http://futureware.biz/mantisconnect')
    ->proxy('https://support.sipwise.com/api/soap/mantisconnect.php',
        options => {compress_threshold => 10_000}
    );
my $ticket_base = 'https://support.sipwise.com/view.php?id=';
my $b64_encode_data = 0; # not needed with our mantis version
my @autozip_patterns = (
    '\.log$', 
    'core\..+\.sig\d+\.\d+$',
);

my $ticket_id = $ARGV[0];
my $file_path = $ARGV[1];

unless(defined $ticket_id && defined $file_path) {
    die "Usage: $PROGRAM_NAME <ticketid> <file>\n";
}

my $fh = IO::File->new($file_path, '<')
    or die "Failed to open file '$file_path': $ERRNO\n";
binmode $fh;

my $file_name = $file_path;
$file_name = basename($file_name);

my $content_type;
my $data;

foreach my $pattern(@autozip_patterns) {
    if($file_name =~ /$pattern/) {
        print "Compression pattern '$pattern' matched, zipping file\n";
        if(zip($fh => \$data, -Level => 9, CanonicalName => 1, Name => $file_name)) {
            $file_name .= '.zip';
            $content_type = 'application/octet-stream';
        } else {
            print "Compression failed ($ZipError), falling back to unzipped file\n";
            $data = undef;
        }
        last;
    }
}
unless($data) {
    print "No compression pattern matched, uploading unzipped file\n";
    $data = do  { local $RS = undef; <$fh> };
    my $file_type = File::Type->new();
    $content_type = $file_type->mime_type($file_path) || 'application/octet-stream';
}
$fh->close;

my $user = prompt('Username:');
my $pass = read_password("Password: ");

if($b64_encode_data) {
    $data = encode_base64($data);
}

my $res = $soap->mc_issue_attachment_add(
    $user, $pass, 
    $ticket_id, $file_name, $content_type, $data);
if(defined $res) {
    if($res->fault) {
        print "Failed to upload '$file_path': " . join(', ', $res->faultcode, $res->faultstring) . "\n";
        exit 1;
    }
}
print "Successfully uploaded to " . $ticket_base . $ticket_id . "\n";
