#!/usr/bin/perl
use strict;
use warnings;
use feature qw(say);
use Filesys::Df;
use Data::Dumper;
use File::Find;
use Archive::Zip qw/ :ERROR_CODES :MISC_CONSTANTS /;
use File::Path qw(remove_tree);
use File::Copy;

# VARS
my($torrentid, $torrentname, $torrentpath) = @ARGV;
my($torrent_dir_path, $torrent_dir_path_clean, $zip_path, $zip_temp_path, $zip_name) = (undef) x 5;

# Open log
my $logfile = '/root/logs/' . $torrentname . '.log';
open(my $fh, '>', $logfile);

# Initialize filepaths
&init_vars();

say $fh "torrentid: $torrentid\ntorrentname: $torrentname\ntorrentpath: $torrentpath";
say $fh "torrent_dir_path: $torrent_dir_path\ntorrent_dir_path_clean: $torrent_dir_path_clean\nzip_path: $zip_path\nzip_temp_path: $zip_temp_path";

# Rename dir
rename($torrent_dir_path, $torrent_dir_path_clean);

# Check if zipping is possible
if (&can_extract($torrent_dir_path_clean)) {
    say $fh 'Enough space for zipping available.';
    
    # Zip
    &zip_torrent($torrent_dir_path_clean, $zip_temp_path);
    
    # Move zip
    move($zip_temp_path, $zip_path);
    
    # Set owner
    &change_owner('www-data', 'www-data', $zip_path);
    
    # Delete torrent dir
    my $removed_count = remove_tree($torrent_dir_path_clean, {
        verbose => 1,
        safe => 1,
    });
}
else {
    say $fh 'Not enough space for zipping available.';
    die 'Not enough space for zipping available.';
}

# Close log
close($fh);

sub change_owner {
    my ($user_name, $group_name, $file_name) = @_;
    
    my $uid = getpwnam $user_name;
    my $gid = getgrnam $group_name;
    chown $uid, $gid, $file_name;
    say $fh 'Successfully changed owner: ' . "$zip_path, User $user_name Group $group_name";
}
sub init_vars {
    $torrent_dir_path = $torrentpath . '/' . $torrentname;
    $zip_name = $torrentname;
    $zip_name =~ s/[^a-zA-Z0-9,]//g;
    $torrent_dir_path_clean = $torrentpath . '/' . $zip_name;
    $zip_path = '/root/VST/' . $zip_name . '.zip';
    $zip_temp_path = $torrentpath . '/' . $zip_name . '.zip';
}
sub zip_torrent {
    my ($path, $zip_path) = @_;
    
    # Init
    my $zip = Archive::Zip->new();
    
    # Add root dir
    $zip->addTree({
        root => $path,
        select => sub {
            say $fh "Storing $_";
            1;
        },
        #compressionLevel = DEFLATING_COMPRESSION_NORMAL,
    });
    
    # Save the Zip file
    unless ( $zip->writeToFileNamed($zip_path) == AZ_OK ) {
        die 'zip write error';
    }
    say $fh 'Zipping successfully: ' . $zip_path;
}
sub can_extract {
    my $torrentpath = shift;
    
    # Free space
    my $df_ref = df('/', 1);
    my $free_space_mb = &size_in_mb($$df_ref{'bavail'});
    say $fh "Free space: " . $free_space_mb;
    
    # Torrent size
    my $torrentsize_mb;
    find(sub { $torrentsize_mb += -s if -f }, $torrentpath);
    $torrentsize_mb = &size_in_mb($torrentsize_mb);
    say $fh "Torrentsize: " . $torrentsize_mb;
    
    if ($torrentsize_mb > $free_space_mb) {
        return 0;
    }
    elsif ($torrentsize_mb < $free_space_mb) {
        return 1;
    }
    else {
        die "Could not determine file relationships";
    }
}
sub size_in_mb {
    my $size_in_bytes = shift;
    return int($size_in_bytes / (1024 * 1024) + 0.5);
}
