# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Immutable::DoubleList {
  version_from SPVM;

  use Fn;
  use Array;
  
  # Interfaces
  interface Countable;
  
  # Fields
  has length : ro int;
  has array : double[];
  
  # Class methods
  static method new : Immutable::DoubleList ($array : double[] = undef) {
    my $length : int;
    if ($array) {
      $length = @$array;
    }
    else {
      $length = 0;
    }
    
    my $self = &new_len($length);
    
    if ($array) {
      Array->memcpy_double($self->{array}, 0, $array, 0, $length);
    }
    
    return $self;
  }
  
  static method new_len : Immutable::DoubleList ($length : int) {
    my $self = new Immutable::DoubleList;
    
    unless ($length >= 0) {
      die "The length \$length must be greater than or equal to 0.";
    }
    
    $self->{length} = $length;
    $self->{array} = new double[$length];
    
    return $self;
  }
  
  # Instance methods
  method get : double ($index : int) {
    my $length = $self->length;
    
    unless ($index >= 0) {
      $index = $length + $index;
    }
    
    unless ($index >= 0) {
      die "The index \$index must be greater than or equal to 0.";
    }
    
    unless ($index < $length) {
      die "The index \$index must be less than the length of \$list.";
    }
    
    my $element = $self->{array}[$index];
    
    return $element;
  }
  
  method to_array : double[] () {
    my $length = $self->length;
    
    my $new_array = new double[$length];
    
    my $array = $self->{array};
    
    Array->memcpy_double($new_array, 0, $array, 0, $length);
    
    return $array;
  }
}
