#!/usr/bin/perl -w


use strict; 

use CGI::Carp qw(fatalsToBrowser); 
use CGI; 

my $gsdl_cgi;
my $gsdl_tmp_dir;

BEGIN {
    
    $|=1; # Force auto-flushing for output

    eval('require "./gsdlCGI.pm"');
    if ($@)
    {
	print STDOUT "Content-type:text/plain\n\n";
	print STDOUT "ERROR: $@\n";
	exit 0;
    }

}


sub get_progress_filename
{
    my ($uploaded_file) = @_;

    my $progress_file = $uploaded_file;

    $progress_file =~ s{^(.*)\/}{}; 
    $progress_file =~ s/\.*?$//;
    $progress_file .= "-progress.txt";

    my $progress_filename = &util::filename_cat($gsdl_tmp_dir, $progress_file);

    return $progress_filename;
}

sub get_file_central_filename
{
    my $file_central = &util::filename_cat($gsdl_tmp_dir,"file-central.txt");

    return $file_central;
}

sub read_file_central
{
    my $fc_filename = get_file_central_filename();

    my @fc_list;

    if (open(FCIN,"<$fc_filename")) {
	
	my $fc_list_str = do { local $/; <FCIN> };
	@fc_list = split(/\n/,$fc_list_str);

	close(FCIN);
    }
    else {
	# OK to have no file-central.txt to start with
	# return empty list
	@fc_list = ();
    }

    return \@fc_list;
    
}

sub remove_from_file_central
{
    my ($filename,$fc_list) = @_;

    my @new_fc_list = ();

    my $removed = 0;

    foreach my $f (@$fc_list) {

	if ($f ne $filename) {
	    push(@new_fc_list,$f);
	}
	else {
	    $removed = 1;
	}
    }

    if (!$removed) {
	print STDERR "Warning: Failed to locate '$filename' in file-central.txt\n";
    }

    return \@new_fc_list;
}

sub add_to_file_central
{
    my ($filename,$fc_list) = @_;

    my @new_fc_list = @$fc_list;

    my $duplicate = 0;
    foreach my $f (@new_fc_list) {

	if ($f eq $filename) {
	    $duplicate = 1;
	}
    }

    if (!$duplicate) {
	push(@new_fc_list,$filename);
    }
    else {
	print STDERR "Warning: Ingoring request to add duplicate entry:\n";
	print STDERR "         '$filename' into file-central.txt\n"
	}

    return \@new_fc_list;
}



sub write_file_central
{
    my ($fc_list) = @_;

    my $fc_filename = get_file_central_filename();

    if (open(FCOUT,">$fc_filename")) {
	
	foreach my $f (@$fc_list) {
	    print FCOUT "$f\n";
	}

	close(FCOUT);
    }
    else {
	print STDERR "Error: Failed to write out $fc_filename\n";
	print STDERR "$!\n";
    }
}

sub monitor_upload 
{            
    my ($uploading_file, $buffer, $bytes_read, $data) = @_;
    
    $bytes_read ||= 0; 
    
    my $progress_filename = get_progress_filename($uploading_file);

    if (! -f $progress_filename) {
	my $fc_list = read_file_central();
	$fc_list = add_to_file_central($uploading_file,$fc_list);
	write_file_central($fc_list);
    }
    
    open(COUNTER, ">$progress_filename"); 
    
    my $per = 0; 
    if ($ENV{CONTENT_LENGTH} > 0) { 
        $per = int(($bytes_read * 100) / $ENV{CONTENT_LENGTH});
    }
    print COUNTER $per;
    close(COUNTER); 
    
    # Useful debug to slow down a 'fast' upload
    # Sleep for 10 msecs
    select(undef, undef, undef, 0.01);
    #select(undef, undef, undef, 0.1);
}



sub upload_file { 

    my ($gsdl_cgi,$full_filename) = @_;
    
    my $fh       = $gsdl_cgi->upload('uploadedfile');
    my $filename = $gsdl_cgi->param('uploadedfile');
    
    return '' if ! $filename;     
    
    open (OUTFILE, '>' . $full_filename) 
        || die("Can't write to $full_filename: $!");        

    binmode(OUTFILE);

    while (my $bytesread = read($fh, my $buffer, 1024)) { 
        print OUTFILE $buffer; 
    } 
    
    close (OUTFILE);
    chmod(0666, $full_filename);  
    
}

sub remove_progress_file 
{ 
    my ($uploaded_file) = @_;

    my $progress_filename = get_progress_filename($uploaded_file);

    if (!unlink($progress_filename)) {
	print STDERR "Warning: Failed to delete $progress_filename\n"; 
    }

    my $fc_list = read_file_central();
    $fc_list = remove_from_file_central($uploaded_file,$fc_list);
    write_file_central($fc_list);
}


sub main { 

    # gsdlCGI->prenew() constructs a 'lite' version of the object where the
    # GSDL environment has been setup
    #
    # This is needed because the main call the gsdlCGI->new takes an 
    # initializer rountine -- monitor_upload() -- as a parameter, AND THAT 
    # routine (which is called before the constructor is finished) needs to 
    # know the tmp directory to use to write out the progress file.

    my $gsdl_config = gsdlCGI->prenew();
    $gsdl_tmp_dir = &util::get_toplevel_tmp_dir();

    require talkback;

    # Use the initializer mechanism so a 'callback' routine can monitor
    # the progress of how much data has been uploaded

    $gsdl_cgi = gsdlCGI->new(\&monitor_upload); 


    require CGI::Ajax;

    my $perlAjax = new CGI::Ajax('check_status' => \&check_status);


    if ($gsdl_cgi->param('process')) { 

	my $uploadedfile = $gsdl_cgi->param('uploadedfile');
	my $full_filename = &util::filename_cat($gsdl_tmp_dir,$uploadedfile);

	my $done_html = &talkback::generate_done_html($full_filename);

        if ($gsdl_cgi->param('yes_upload')) { 
            upload_file($gsdl_cgi,$full_filename); 
        }   

        print $gsdl_cgi->header(); 
        print $done_html; 

        remove_progress_file($gsdl_cgi->param('uploadedfile'));   
    }
    else {         

	my $upload_html_form;

	#my $oid     = $gsdl_cgi->param('oid');
	#my $collect = $gsdl_cgi->param('collect');
	my $uniq_file = $gsdl_cgi->param('uploadedfile');   

	#my $uniq_file = "$collect-$oid-doc.xml";
	# Light-weight (hidden) form with progress bar

	$upload_html_form 
	    = &talkback::generate_upload_form_progressbar($uniq_file);
	
        print $perlAjax->build_html($gsdl_cgi, $upload_html_form);
    }
}


main(); 


#=====

sub inc_wait_dots
{
    my $wait_filename = &util::filename_cat($gsdl_tmp_dir,"wait.txt");
    open(WIN,"<$wait_filename");
    my $wait = <WIN>;
    close(WIN);

    $wait = ($wait+1) %6;
    my $wait_dots = "." x ($wait+1);

    open(WOUT,">$wait_filename");
    print WOUT "$wait\n";
    close(WOUT);

    return $wait_dots;
}


sub check_status_single_file
{
    my ($filename) = @_;
    
    my $monitor_filename = get_progress_filename($filename);

    if (! -f  $monitor_filename ) {
	return "";
    }
                
    open my $PROGRESS, '<', $monitor_filename or die $!;
    my $s = do { local $/; <$PROGRESS> };
    close ($PROGRESS); 
    
    my $fgwidth = int($s * 1.5); 
    my $bgwidth = 150 - $fgwidth;
  
    my $fgcol = "background-color:#dddd00;";
    my $bgcol = "background-color:#008000;";

    my $style_base = "height:10px; float:left;";

    my $r = "";
    $r .= "<div>$filename:</div>";
    $r .= "<nobr>";
    $r .= "<div style=\"width: ${fgwidth}px; $fgcol $style_base\"></div>"; 
    $r .= "<div style=\"width: ${bgwidth}px; $bgcol $style_base\"></div>";
    $r .= "<div style=\"float:left; width: 80px\">&nbsp;$s%</div>"; 
    $r .= "</nobr>";
    $r .= "<br />";

    return $r; 
}


sub check_status_all
{
    my $file_central = get_file_central_filename();

    my $html = "";

    my $fc_list = read_file_central();

    foreach my $f (@$fc_list) {
	$html .= check_status_single_file($f);
    }

    return $html;

}

 
# Accessed from HTML web page through the majic of perlAjax 

sub check_status 
{    

    my $wait_dots = inc_wait_dots();
    my $html = "$wait_dots<br>";

    my $filename = $gsdl_cgi->param('uploadedfile');

    if ((defined $filename) && ($filename ne "")) {
	$html .= check_status_single_file($filename);
    }
    else {
	$html .= check_status_all();
    }

    return $html;
}
