# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

package PBot::SelectHandler;
use parent 'PBot::Class';

use warnings; use strict;
use feature 'unicode_strings';

use IO::Select;

sub initialize {
    my ($self, %conf) = @_;
    $self->{select}  = IO::Select->new();
    $self->{readers} = {};
    $self->{buffers} = {};
}

sub add_reader {
    my ($self, $handle, $sub) = @_;
    $self->{select}->add($handle);
    $self->{readers}->{$handle} = $sub;
    $self->{buffers}->{$handle} = "";
}

sub remove_reader {
    my ($self, $handle) = @_;
    $self->{select}->remove($handle);
    delete $self->{readers}->{$handle};
    delete $self->{buffers}->{$handle};
}

sub do_select {
    my ($self) = @_;
    my $length = 8192;
    my @ready  = $self->{select}->can_read(.1);

    foreach my $fh (@ready) {
        my $ret = sysread($fh, my $buf, $length);

        if (not defined $ret) {
            $self->{pbot}->{logger}->log("Error with $fh: $!\n");
            $self->remove_reader($fh);
            next;
        }

        if ($ret == 0) {
            if (length $self->{buffers}->{$fh}) { $self->{readers}->{$fh}->($self->{buffers}->{$fh}); }
            $self->remove_reader($fh);
            next;
        }

        $self->{buffers}->{$fh} .= $buf;

        if (not exists $self->{readers}->{$fh}) { $self->{pbot}->{logger}->log("Error: no reader for $fh\n"); }
        else {
            if ($ret < $length) {
                $self->{readers}->{$fh}->($self->{buffers}->{$fh});
                $self->{buffers}->{$fh} = "";
            }
        }
    }
}

1;