package XXV::MODULES::SVDRP;

use IO::Socket::INET;
use Tools;
use Locale::gettext;
use strict;

$|++;

# This module method must exist for XXV
# ------------------
sub module {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $args = {
        Name => 'SVDRP',
        Description => gettext('This module a telnet client for sdvrp.'),
        Version => '0.01',
        Date => '07.09.2004',
        Author => 'xpix',
        Preferences => {
            VdrHost => {
                description => gettext('Name of the host that runs vdr'),
                default     => 'localhost',
                type        => 'string',
                required    => gettext('This is required!'),
            },
            VdrPort => {
                description => gettext('SVDRP-port of the running vdr client'),
                default     => 2001,
                type        => 'integer',
                required    => gettext('This is required!'),
            },
        },
        Commands => {
            sstatus => {
                description => gettext('Status from svdrp'),
                short       => 'ss',
                callback    => sub{ $obj->status(@_) },
                Level       => 'user',
            },
            scommand => {
                description => gettext('Send a command to svdrp'),
                short       => 'sc',
                callback    => sub{ $obj->scommand(@_) },
                Level       => 'admin',
            },
        },
    };
    return $args;
}

# ------------------
sub new {
# ------------------
	my($class, %attr) = @_;
	my $self = {};
	bless($self, $class);

    # paths
    $self->{paths} = delete $attr{'-paths'};

	# who am I
    $self->{MOD} = $self->module;

    # all configvalues to $self without parents (important for ConfigModule)
    map {
        $self->{$_} = $attr{'-config'}->{$self->{MOD}->{Name}}->{$_} || $self->{MOD}->{Preferences}->{$_}->{default}
    } keys %{$self->{MOD}->{Preferences}};

    # read the DB Handle
    $self->{dbh} = delete $attr{'-dbh'};

    $self->{COMMANDS} = [];

	return $self;
}

# ------------------
sub connect {
# ------------------
    my $obj = shift || return error ('No Object!' );

    lg sprintf('Connect to SVDRP Host: "%s:%d"',
            $obj->{VdrHost},
            $obj->{VdrPort},
        );

	my $SOCKET = IO::Socket::INET->new(
		PeerAddr => $obj->{VdrHost},
		PeerPort => $obj->{VdrPort},
		Proto => 'tcp',
        Type => SOCK_STREAM,
        Timeout => 1,
	) or return error($@);
    return $SOCKET;
}

# ------------------
sub queue_cmds {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    my $cmd = shift  || 'CALL';

    if($cmd eq 'CALL') {
        my $erg = $obj->command($obj->{COMMANDS});
        $obj->{COMMANDS} = [];
        return $erg;
    } elsif($cmd eq 'COUNT') {
        return scalar @{$obj->{COMMANDS}};
    } else {
        push(@{$obj->{COMMANDS}}, $cmd);
    }
}

# ------------------
sub command {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $cmd = shift || $obj->{COMMANDS} || return error ('No Commands!');

    my @commands = ();
    push(@commands, (ref $cmd eq 'ARRAY' ? @$cmd : $cmd));

    # Put Command follow quit and read Output
    my $socket = $obj->connect() or return error('Could not open the svdrp-socket!');
    my $tosocket;
    foreach my $command (@commands) {
        lg sprintf('Call command "%s" on svdrp',
            $command,
            );
        $tosocket .= sprintf("%s\r\n", $command);
    }
    $tosocket .= sprintf("%s\r\n", 'quit');
    print $socket $tosocket;

    my (@Data, $Line);
	while(defined ($Line = <$socket>)) {
		$Line =~ s/\r\n//g;
		push(@Data, $Line);
	};
    $socket->close();

    my $output = $obj->parse(\@Data, \@commands);

    return $output;
}

# ------------------
sub status {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $watcher = shift || return error ('No Watcher!');
    my $console = shift || return;

    my $erg = $obj->command('stat disk');
    $console->msg($erg, $obj->err)
        if(ref $console);
}

# ------------------
sub scommand {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $watcher = shift || return error ('No Watcher!');
    my $console = shift || return error ('No Console');
    my $text = shift || return $console->message(gettext("No Command! Please use scommand 'cmd'"));

    my $erg = $obj->command($text);
    $console->msg($erg, $obj->err);
}

# ------------------
sub parse {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $data = shift || return error ('No Data to parse!');
    my $commands = shift || return error ('No Commands to parse!');

    my @ret;
    my $error = 0;

    main::getVdrVersion($1)
        if($data->[0] =~ /SVDRP\s+VideoDiskRecorder\s+(\d\.\d\.\d+)\;/);

    foreach my $zeile (@$data) {
        if($zeile =~ /^(\d{3})\s+(.+)/) {
            $error = $2 if(int($1) >= 500);
        }
    }
    if($error) {
        $obj->{ERROR} = sprintf("The command(s) [%s] produced an error: %s", join(', ', @$commands), $error);
    } else {
        $obj->{ERROR} = 0;
    }
    return $data;
}

# ------------------
sub err {
# ------------------
    my $obj = shift  || return error ('No Object!' );
    return $obj->{ERROR};
}


1;
