package Empeg::Emptool;

=pod

=head1 NAME

Empeg::Emptool - Perl wrapper for emptool

=head1 SYNOPSIS

    use Empeg;

    my $et = new Empeg::Emptool("emptool 10.0.0.201");
    $et->chdir("artists");
    $et->mklist("foo");
    $et->chdir("foo");
    $et->upload("bar.mp3");

    $et->sync();

=head1 METHODS

=cut


use IPC::Open2;
use Data::Dumper;
use FileHandle;


=head2 new ( command )

Returns a new Empeg::Emptool object, wrapping the emptool command line
given.

=cut
sub new {
    my $class = shift;
    my($command) = @_;
    my $self = {};
    bless $self, $class;
	
	$self->{rdfh} = new FileHandle;
    $self->{wrfh} = new FileHandle;
    my $pid = open2($self->{rdfh}, $self->{wrfh}, $command); 

    $self->_read_output();
    return $self;
}

sub _read_output($$) {
    my $self = shift;
    my($progress) = @_;
    my $buf = '';
    my $bb;
    while(!eof($self->{rdfh}) and sysread($self->{rdfh}, $bb, 1024) != 0 ) {
        $buf .= $bb;
        if($progress) {
            print $bb;
        }
        if($buf =~ m/^(\/.*)>/m) {
            $self->{pwd} = $1;
            last;
        }
    }
    if(eof($self->{rdfh})) {
        print $buf;
        die "emptool died.";
    }
    my @ret;
    while($buf =~ m/^(\d{4})\s+(.*)$/gm)  {
        push @ret, {
            code => $1,
            string => $2
        };
    }
    return @ret;
}

sub _do_command($$$) {
    my $self = shift;
    my($command, $progress) = @_;

    my $b = $command . "\n";
    $self->{wrfh}->syswrite($b, length($b));
    $self->_read_output($progress);
}

sub _do_simple_command {
    my $self = shift;
    my($command, $good, $bad) = @_;
    my @ret = $self->_do_command($command,0);
    foreach my $ret (@ret) {
        foreach(@$good) {
            if($_ == $ret->{code}) {
                return 1;    
            }
        }
        foreach(@$bad) {
            if($_ == $ret->{code}) {
                return 0;
            }
        }
        print "Unknown response to chdir: $ret->{code} $ret->{string}\n";
    }
    print "No known response to command: $command\n";
    return 0;
}

=head2 chdir ( dir )

Change to specified directory.  Returns 1 or 0 to indicate success or
failure.  Can be used to test for the existence of a directory.

=cut
sub chdir($$) {
    my $self = shift;
    my($dir) = @_;
    return $self->_do_simple_command("cd \"$dir\"",[2403],[4404,4302]); 
}

=head2 mklist ( list )

Creates a new play list.

=cut
sub mklist($$) {
    my $self = shift;
    my($list) = @_;
    return $self->_do_simple_command("mklist \"$list\"",[2404],[]);
}

=head2 upload ( file )

Uploads the given file

=cut
sub upload($$) {
    my $self = shift;
    my($file) = @_;
    return $self->_do_simple_command("upload \"$file\"",[2402],[]);
}

=head2 sync

Commits outstanding transactions.

=cut
sub sync($) {
    my $self = shift;
    my @ret = $self->_do_command("sync",1);
    foreach(@ret) {
        if($_->{code} == 2129) {
            return 1;
        }
    }
    return 0;
}

=head2 exists ( file )

Uses ls to determine if "file" exists.

=cut
sub exists($$) {
    my $self = shift;
    my($file) = @_;
    my @ret = $self->_do_command("ls \"$file\"",0);
    foreach(@ret) {
        if($_->{code} == 4404) {
            return 0;
        }
    }
    return 1;
}

=head2 pwd

Gets the current directory.

=cut
sub pwd($) {
    my $self = shift;
    return $self->{pwd};
}

1;
