# Copyright (c) 2023 Yuki Kimoto
# MIT License

class StringList extends List {
  version_from SPVM;
  
  use Fn;
  use Array;
  
  interface Cloneable;
  interface Countable;
  
  # Class methods
  static method new : StringList ($array : string[] = undef, $capacity : int = -1) {
    my $self = new StringList;
    
    unless ($array) {
      $array = new string[0];
    }
    
    $self->SUPER::init($array, $capacity);
    
    return $self;
  }
  
  static method new_len : StringList ($length : int, $capacity : int = -1) {
    my $self = new StringList;
    
    my $proto = new string[0];
    
    $self->SUPER::init_len($proto, $length, $capacity);
    
    return $self;
  }
  
  static method new_ref : StringList ($array : string[]) {
    
    unless ($array) {
      die "The array \$array must be defined.";
    }
    
    my $self = new StringList;
    
    $self->{array} = $array;
    
    return $self;
  }
  
  # Instance methods
  method get : string ($index : int) {
    return (string)$self->SUPER::get($index);
  }
  
  method insert : void ($index : int, $element : string) {
    $self->SUPER::insert($index, $element);
  }
  
  method pop : string () {
    return (string)$self->SUPER::pop;
  }
  
  method push : void ($element : string) {
    $self->SUPER::push($element);
  }
  
  method remove : string ($index : int) {
    return (string)$self->SUPER::remove($index);
  }
  
  method replace : void ($offset : int, $remove_length : int, $replace : string[] = undef) {
    $self->SUPER::replace($offset, $remove_length, $replace);
  }
  
  method splice : string[] ($offset : int, $remove_length : int, $replace : string[] = undef) {
    return (string[])$self->SUPER::splice($offset, $remove_length, $replace);
  }
  
  method set : void ($index : int, $element : string) {
    $self->SUPER::set($index, $element);
  }
  
  method shift : string () {
    return (string)$self->SUPER::shift;
  }
  
  method to_array : string[] () {
    return (string[])$self->SUPER::to_array;
  }
  
  method unshift : void ($element : string) {
    $self->SUPER::unshift($element);
  }
  
  method clone : StringList () {
    
    my $clone = &new_len($self->length, $self->capacity);
    
    for (my $i = 0; $i < $self->length; $i++) {
      $clone->{array}->[$i] = copy (string)$self->{array}->[$i];
    }
    
    return $clone;
  }
  
  method push_ : void ($elements : string[]) {
    
    unless ($elements) {
      die "The elements \$elements must be defined.";
    }
    
    for my $element (@$elements) {
      $self->push($element);
    }
    
  }
  
  method unshift_ : void ($elements : string[]) {
    
    unless ($elements) {
      die "The elements \$elements must be defined.";
    }
    
    for (my $i = @$elements - 1; $i >= 0; $i--) {
      my $element = $elements->[$i];
      $self->unshift($element);
    }
    
  }
  
  method get_array : string[] () {
    return (string[])$self->{array};
  }
  
}
