package SPVM::IO::Select {
  use SPVM::IntList;
  
  has handles : SPVM::IntList;
  
  sub new : SPVM::IO::Select () {
    my $self = new SPVM::IO::Select;
    
    $self->{handles} = SPVM::IntList->new;
    
    return $self;
  }

  sub add : int ($self : self, $new_handle : int) {
    
    my $found = 0;
    my $handles = $self->{handles};
    
    for (my $i = 0; $i < $handles->length; $i++) {
      my $handle = $handles->get($i);
      
      if ((int)$handle == $new_handle) {
        $found = 1;
        last;
      }
    }
    
    if ($found) {
      return 0;
    }
    else {
      $handles->push($new_handle);
      return 1;
    }
  }

  sub remove : int ($self : self, $remove_handle : int) {
    
    my $new_handles = SPVM::IntList->new;
    my $handles = $self->{handles};
    
    my $removed = 0;
    for (my $i = 0; $i < $handles->length; $i++) {
      my $handle = $handles->get($i);
      
      if ((int)$handle == $remove_handle) {
        $removed = 1;
      }
      else {
        $new_handles->push($handle);
      }
    }
    
    $self->{handles} = $new_handles;
    
    return $removed;
  }
  
  sub exists : int ($self : self, $check_handle : int) {
    
    my $handles = $self->{handles};
    
    for (my $i = 0; $i < $handles->length; $i++) {
      my $handle = $handles->get($i);
      
      if ((int)$handle == $check_handle) {
        return 1;
      }
    }
    
    return 0;
  }

  sub handles : int[] ($self : self) {
    return $self->{handles}->to_array;
  }

  sub can_read : int[] ($self :self, $timeout : double) {
    my $handles = $self->{handles};
    
    return $self->_can_read($handles->to_array, $timeout);
  }
  
  native private sub _can_read : int[] ($self :self, $handles : int[], $timeout : double);

  sub can_write : int[] ($self :self, $timeout : double) {
    my $handles = $self->{handles};
    
    return $self->_can_write($handles->to_array, $timeout);
  }
  
  native private sub _can_write : int[] ($self :self, $handles : int[], $timeout : double);

  sub has_exception : int[] ($self :self, $timeout : double) {
    my $handles = $self->{handles};
    
    return $self->_has_exception($handles->to_array, $timeout);
  }
  
  native private sub _has_exception : int[] ($self :self, $handles : int[], $timeout : double);
}
