package A2B::Tool;

use A2B::Table::Element;
use A2B;

use Cwd;

use strict;

use vars qw(@ISA);

@ISA = qw(A2B::Table::Element);

use overload '""' => \&as_string;

sub as_string {
	my ($self, $details) = @_;
	my $options = $details;
	my $all_args = $details >= 2;
	my $cmd;
	if ($options) {
		$cmd = $self->command_line;
		if (!$all_args) {
			my %already;
			$cmd = join ' ', $self->tool, grep { !$already{$_}++ } $cmd =~ /(\${.*?})/g;
		}
	} else {
		$cmd = $self->tool;
	}
	return $cmd;
};

# logic: special options that could not simply be represented in the tools file
sub logic {
	my ($self, $command, $ext) = @_;
	my $tool = $self->tool;
#	warn "logic: $tool $ext $command\n";
	if ($tool eq "mplayer" || $tool eq "mencoder") {
		if ($ext eq "mov" || $ext eq "mp4" || $ext eq "3gp") {
			$command =~ s/\b$tool\b/$tool -demuxer mov/g;
		}
	}
	return $command;
}

sub find_files {
	my ($self, $type) = @_;
	if ($type eq "inode/directory") {
		my @dirs = `find . -maxdepth 1 -mindepth 1 -type d`;
		chomp for @dirs;
		if (@dirs == 1) {
			return map {"$_/"} @dirs;
		} else {
			return "./";
		}
	}
	my @files = `find -L -type f | sort`;  # XXX may be a bad thing, to use find - e.g. speed, portability
#	die "cant use `find'" unless @files;
	for (@files) { chomp; s|^\./||; }
	return @files;
}

sub command_line {
	my ($self) = @_;

	my $tool = $self->tool;
	my $command = $self->invoke;
	unless ($command =~ s/\$t\b/$tool/g) {
		$command = "$tool $command";
	}

	my $nopts = $ENV{$tool."_nopts"};
	if ($nopts) {
		if (!A2B->quiet && !A2B->a2b->{using_already}{"${tool}_nopts"}++) { warn "using ${tool}_nopts $nopts\n"; }
		for my $nopt (split /\s{2,}/, $nopts) {
			$command =~ s/\b\Q$nopt\E\b//g;
		}
	}

	$command = join " ",
	  map {
	    if (/^\w[\w-]*$/) {
	      my $opts = $ENV{$_."_opts"};
	      if ($opts && !A2B->quiet && !A2B->a2b->{using_already}{"${tool}_opts"}++) { warn "using $tool ${_}_opts = $opts\n"; }
	      $opts ? "$_ $opts" : $_;
	    } else { $_ }
	  }
	  split /\s+/, $command;

	return $command;
}

sub convert {
	my ($self, @from_files) = @_;
	
	# we assume that we are in a safe, preferably empty box to do all this!

	my @files_before = $self->find_files("");

	my $tool = $self->tool;
	my $command = $self->command_line;

	$command =~ /(\$i|\@i|\@,i)\b/ or
		die "database invalid for $tool: invoke field has no \$i, \@i or \@,i";

	my $dir = getcwd;
	my $i = 1;
	$command =~ s{(^|\s)a2b(\s)}{my $x = "$1a2b -D=$i$2"; ++$i; $x}ge;

	my $extension = $self->to->extension;

	my $a2b = A2B->a2b;
	my $type = $a2b->identify_by_content_first($from_files[0]);
	my $ext = $a2b->type($type)->extension;
	$command =~ s/\$ix\b/$ext/g;
	$command =~ s/\$ox\b/$extension/g;
	$command = $self->logic($command, $ext);
	if ($command =~ /(\@i|\@,i)\b/) {
		my $out_file = "output.$extension";
		-e $out_file and
			die "target `$out_file' already exists\n";
		$command =~ s/\@i\b/join " ", map {"\Q$_\E"} @from_files/eg;
		$command =~ s/\@,i\b/join ",", map {"\Q$_\E"} @from_files/eg;
		$command =~ s/\$i\b/"\Q$from_files[0]\E"/eg;
		$command =~ s/\$o\b/"\Q$out_file\E"/eg;
		$self->do_command($command) or
			warn "command failed";
	} else {
		for my $file (@from_files) {
			my $com = $command;
			$com =~ s/\$i\b/\Q$file\E/g;
			if ($com =~ /\$o\b/) {
				(my $out_file = $file) =~ s/(?:\.[^\.]*)?$/.$extension/;
				if ($out_file =~ m{://}) {
					$out_file =~ s{.*/}{};
					if ($out_file =~ m{^\.} or $out_file eq "") {
						$out_file = "a2b-out$out_file";
					}
				}
				-e $out_file and
					die "target `$out_file' already exists\n";
				$com =~ s/\$o\b/\Q$out_file\E/g;
			}
			$self->do_command($com) or
				warn "command failed";
		}
	}

	my @files = $self->find_files($self->to->type);

	my %files_before = map {$_, 1} @files_before;

	my @new_files;
	for (@files) {
		push @new_files, $_ unless $files_before{$_};
	}

	return @new_files;
}

sub do_command {
	my ($self, $command) = @_;
	if (A2B->quiet <= 1) {
		print "$command\n";
	}
	if (A2B->quiet) {
		$command = "exec >/dev/null 2>&1; $command";
	}
	return not system "$command";
}

1
