#!/usr/bin/env perl
# ex:ts=4

use strict;
use warnings;

use Digest::MD5;
use Getopt::Long;
use LWP::UserAgent;

# Default values.
my $wwwsite = 'www.retroroms.net';
my $dbsite = 'bda.retroroms.net';
my $login = '';
my $password = '';
my $realm = 'Bulk Download Area';
my $chdmode = 0;

sub fileget {
	my ($ua, $subdir, $file, $msg) = @_;

	open(my $fh, ">$file") or die "Cannot open \"$file\": $!\n";
	binmode $fh;
	print $msg;

	my $done = 0;
	my $res = $ua->get("http://$dbsite/downloads/mame/$subdir/$file",
		':read_size_hint' => 4096,
		':content_cb' => sub {
			my ($chunk, $res, $proto) = @_;

			$done += length($chunk);
			my $pct = sprintf("%.1f", $done / ($res->content_length / 100));
			print $fh $chunk;
			print "\r$msg$pct%";
		}
	);
	close $fh;

	if (!$res->is_success) {
		print "\r${msg}Failed (" . $res->status_line . ")\n";
		unlink $file unless $done > 0;
	} else {
		# The trailing space prevents having leftover characters.
		print "\r${msg}Done. \n";
	}
	return $res;
}

sub romget {
	my ($ua, $rom) = @_;

	fileget($ua, 'currentroms', "$rom.zip", "Fetching rom \"$rom\"... ");
}

sub chdget {
	my ($ua, $chd) = @_;

	my $file = "$chd.md5";
	my $res = fileget($ua, "CHDs/$chd", $file, "Fetching \"$file\"... ");
	if (!$res->is_success) {
		die "Cannot get \"$file\", aborting.\n";
	}
	open (my $fh, "<$file") or die "Cannot open \"$file\": $!\n";
	while (<$fh>) {
		my ($want, $file) = split;
		next if $file eq "$chd.chd";

		# If the file already exists, check its MD5 checksum.
		if (-f $file) {
			my $md5 = Digest::MD5->new;
			open(my $part, "<$file") or die "Cannot open \"$file\": $!\n";
			binmode $part;
			$md5->addfile($part);
			close $part;
			if ($want eq $md5->hexdigest) {
				print "Skipping already downloaded file \"$file\".\n";
				next;
			}
		}
		$res = fileget($ua, "CHDs/$chd", $file, "Fetching \"$file\"... ");
		# Be nice to the server if an error occured.
		sleep 10 if $res->code =~ /^5\d\d$/;
	}
	close $fh;
}

$| = 1;	# Put STDOUT in non-buffered mode.

my %options = (
	"user|u=s" => \$login,
	"password|p=s" => \$password,
	"chd|c" => \$chdmode
);
GetOptions(%options) or exit 1;

my $ua = LWP::UserAgent->new;
$ua->agent('Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8.1.6) Gecko/20070801 Firefox/2.0.0.6');
$ua->credentials("$dbsite:80", $realm, $login, $password);
$ua->cookie_jar({});	# Enable cookies.

# We need to login to the main site before being able to download.
print "Logging onto $wwwsite.\n";
my $res = $ua->post("http://$wwwsite/user.php",
	{ uname => $login, pass => $password });
if (!$res->is_success) {
	die "Cannot login to main site: " . $res->status_line . "\n";
}

foreach my $rom (@ARGV) {
	eval {
		if (!$chdmode) {
			romget($ua, $rom);
		} else {
			chdget($ua, $rom);
		}
	};
	if ($@) {
		print STDERR $@;
		next;
	}
}
