#!/usr/bin/perl -w

use Net::FTP;
use strict;

my $host = shift || "host";
my $cwd = "~" ;
my $local_dir = '/home/dasn/pool/download';
my $prompt = "$host $cwd> ";
my $ftp;
my $flag_force; 	# Force to conn another host

my %dir_list;
my %download_files;
$SIG{'INT'} = 'int_handler';

&lcd($local_dir);
print $prompt;

while(<STDIN>) {
	if (/^\s*(\w+)\s*(.*)$/) { # command line process
		my ($cmd, $param) = ($1, $2);

		if($cmd eq 'quit') {
			&quit;
		} elsif($cmd eq 'conn') {
			$flag_force = 1;
			&conn($param);
		} elsif($cmd eq 'cd') {
			&chdir($param);
		} elsif($cmd eq 'ls') {
			&ls($param);
		} elsif($cmd eq 'get') {
			&get($param);
		} elsif($cmd eq 'lcd') {
			&lcd($param);
		} elsif($cmd eq 'quot') {
			&quot($param);
		} elsif($cmd eq 'disconn') {
			&disconn;
		} else {
			print "Unknown command: $cmd\n"
		}
	} elsif (/^\s*$/) { 
	} else {
		print "Invalid command!\n";
	}

	$prompt = "$host $cwd> ";
	print $prompt;
}

sub quot
{
	&conn($host) unless ($ftp);
	$ftp->quot($_[0]);
}
sub lcd
{
	if (defined($_[0])) {
		$local_dir = $_[0];
		%download_files = ();
		chdir $_[0] or die "Cannot change to $_[0]: $!";
		opendir DIR, $_[0] or die "Cannot open $_[0]: $!";

		print STDERR "Reading download files...";
		for (readdir DIR) {
			next if (/^\./);
			next unless -f $_ and -r $_ and -w $_;
			my @temp_stat = stat;
			$download_files{$_} = $temp_stat[7];
		}
		print STDERR "done\n";
		closedir DIR;
	} else {
		print "$local_dir\n";
	}
}

sub int_handler
{
	$ftp->abort() if $ftp;
	print STDERR $prompt;
}
sub confirm
{
	print "$_[0] (Y/n) ";
	my $line = <STDIN>;

	if ($line =~ /^\s*y.*$|^\s*$/i) {
		return 1;
	}elsif ($line =~ /^\s*n.*$/i) {
		return 2;
	}else {
		return 3;
	}
}

sub disconn
{
	$ftp->quit() if ($ftp);
}

sub quit 
{ 
	&disconn;
	exit(0) 
}

sub conn 
{
	if ( defined $_[0] ) {
		$host = $_[0];
	} else {
		print "Invalid host name.\n";
		return undef;
	}

	if (!$ftp || $flag_force) {
		$ftp = Net::FTP->new("$host", Debug=>5, 
			Hash=>\*STDERR, Passive=>1, Port=>21, Timeout=>60) 
				or return undef;
		
		$ftp->login("anonymous", "unknown\@unknown.com")
		or warn "Cannot login ", $ftp->message;

		$cwd=$ftp->pwd();
		$ftp->binary;
		$ftp->hash(\*STDERR, 10240); # one mark per block

		$flag_force = undef;
		%dir_list = (); # clear hash
		1;
	}
}

sub chdir 
{
	my $dir;
	&conn($host) unless ($ftp);


	if ($_[0]) {
		$dir = $_[0] 
	} else {
		$cwd=$ftp->pwd();
		print "Current DIR is $cwd\n";
		return
	}
		
	$ftp->cwd("$dir");
	$cwd=$ftp->pwd();
}

sub ls 
{
	unless ($ftp) {
		unless ( &conn($host) ) {
			warn "Connect to \"$host\" error";
			return undef;
		}
	}

	if ($_[0]) {
		print "Not support\n";
		return
	} else {
		unless ($dir_list{$cwd}) {
			$dir_list{$cwd}	= $ftp->dir()
		}
		print "$_\n" for (@{$dir_list{$cwd}})
	}
}

sub get 
{
	my ($full_name, $remote_size);
	my $msg = "File exists, Wanna continue downloading from the last session?";

	unless ($ftp) {
		&conn($host)
	}


	if ($_[0]) {
		unless ( $download_files{$_[0]} ) {
			$ftp->get($_[0]) or warn "Getting file error: $!";
		} elsif ( confirm($msg) == 1) {
			if ( rindex( $cwd, '/' ) == (length( $cwd ) - 1) ){ 
				# strip the last '/' of string
				$cwd = substr($cwd,  0,  -1)
			}
			$full_name = $cwd . "/". $_[0];

			#$remote_size = $ftp->size($full_name)
			#	or warn "Can't get file size: $_[0]";

			print "Continue downloading...\n";
			until ($ftp->get($full_name, $_[0], $download_files{$_[0]}))
			{
				warn "Continue downloading error, try again!\n";
				&lcd($local_dir);
				&conn($host);
			}
		} else {
			print "Resume downloading...\n";
			$ftp->get($_[0]) or warn "Getting file error: $!";
		}
	} else { print "File name needed.\n"}
}
