package XXV::MODULES::INTERFACE;

use Locale::gettext;
use XXV::OUTPUT::Dump;
use IO::Socket::INET;
use Tools;

use strict;

# This module method must exist for XXV
# ------------------
sub module {
# ------------------
    my $obj = shift || return error ('No Object!' );
    my $args = {
        Name => 'INTERFACE',
        Description => gettext('This module is a multichannel telnet server with dumped output for second party software.'),
        Version => '0.01',
        Date => '06.09.2004',
        Author => 'xpix',
        Preferences => {
            active => {
                description => gettext('Activate this service'),
                default     => 'y',
                type        => 'confirm',
                required    => gettext('This is required!'),
            },
            Clients => {
                description => gettext('Maximum number of allowed connections at a time'),
                default     => 5,
                type        => 'integer',
                required    => gettext('This is required!'),
            },
            Port => {
                description => gettext('Portnumber to connect the client'),
                default     => 8002,
                type        => 'integer',
                required    => gettext('This is required!'),
            },
        },
    };
    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'};

    # The Initprocess
    $self->init or return error('Problem to initialze Module');

	return $self;
}

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

    # globals
    my $channels;

    my $prompt = "XXV> ";

    # make socket
	my $socket = IO::Socket::INET->new(
		Listen		=> $obj->{Clients} || 5,
		LocalPort	=> $obj->{Port}    || 8002,
		Reuse		=> 1);
	warn sprintf("[Fatal] Cannot build initial socket for %s on port %d. [%s]\n",
	        $obj->{Name}, $obj->{Port}, $!) unless $socket;

    # install an initial watcher
    Event->io(
        fd => $socket,
        prio => -1,  # -1 very hard ... 6 very low
        cb => sub {
                # make "channel" number
                my $channel=++$channels;

                # accept client
                my $client=$socket->accept;
                warn "[Error] Cannot connect interface to new client.\n" and return unless $client;
                $client->autoflush;

                my $console = XXV::OUTPUT::Dump->new(
                    -handle => $client,
                    -dbh    => $obj->{dbh},
                );

                # install a communicator
                Event->io(
                    fd => $client,
                    prio => -1,  # -1 very hard ... 6 very low
                    cb => sub {
                            my $watcher = shift;

                            # read new line and report it
                            my $handle=$watcher->w->fd;

                            my $line=<$handle>;
                            unless($line) {
                                $watcher->w->cancel;
                                $handle->close();
                                undef $watcher;
                                return 1;
                            }
                            $line =~ s/[\r|\n]//sig
                                if(defined $line);

                            $obj->handleInput($watcher, $console, $line);
                        },
                );

                # welcome
                $client->print(sprintf(gettext("Welcome to XXV System Ver.: %s.\r\nThis is session %s.\r\n---\r\nEOF\r\n"),
                    $obj->{MOD}->{Version}, $channel));

                my $userMod = main::getModule('USER');
                unless(exists $console->{USER} or $userMod->{active} ne 'y') {
                    # Login
                    my $data = $console->login(gettext("Welcome to xxv System. Please Login:"));
                    my $user = $userMod->check($client, $data->{Name}, $data->{Password});
                    if(exists $user->{Name}) {
                        $console->{USER} = $user;
                    } else {
                        $console->message(gettext("Sorry, but permission denied!"));
                        $client->close;
                        return 1;
                    }
                }
            },
    ) if($obj->{active} eq 'y');

    return 1;

}

# ------------------
sub handleInput {
# ------------------
    my $obj     = shift || return error ('No Object!' );
    my $telnet = main::getModule('TELNET');
    my $ret = $telnet->handleInput(@_);
}

1;
