# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Immutable::StringList {
  version_from SPVM;

  use Fn;
  use Array;
  
  # Interfaces
  interface Countable;
  
  # Fields
  has length : ro int;
  has array : string[];
  
  # Class methods
  static method new : Immutable::StringList ($array : string[] = undef) {
    my $length : int;
    if ($array) {
      $length = @$array;
    }
    else {
      $length = 0;
    }
    
    my $self = &new_len($length);
    
    if ($array) {
      for (my $i = 0; $i < $length; $i++ ) {
        my $value = copy $array->[$i];
        make_read_only $value;
        $self->{array}[$i] = $value;
      }
    }
    
    return $self;
  }
  
  static method new_len : Immutable::StringList ($length : int) {
    my $self = new Immutable::StringList;
    
    unless ($length >= 0) {
      die "The length \$length must be greater than or equal to 0.";
    }
    
    $self->{length} = $length;
    $self->{array} = new string[$length];
    
    return $self;
  }
  
  # Instance methods
  method get : string ($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 : string[] () {
    my $length = $self->length;
    
    my $new_array = new string[$length];
    
    my $array = $self->{array};
    
    Array->memcpy_string_address($new_array, 0, $array, 0, $length);
    
    return $new_array;
  }
}