# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Regex::Match {
  version_from Regex;
  
  allow Regex;
  
  use Hash;
  use Array;
  
  has success : ro byte;
  
  has captures : ro string[]
    get {
      unless (exists $self->{captures}) {
        $self->{captures} = new string[0];
      }
      
      return $self->{captures};
    }
  ;
  
  has match_start : ro int
    get {
      unless (exists $self->{match_start}) {
        $self->{match_start} = -1;
      }
      
      return $self->{match_start};
    }
  ;
  
  has match_length : ro int;
  
  # Class Method
  static method new : Regex::Match ($options : object[] = undef) {
    
    my $option_names = [
      "success",
      "match_start",
      "match_length",
      "captures",
    ];
    
    Fn->check_option_names($options, $option_names);
    
    my $self = new Regex::Match;
    
    my $options = Hash->new($options);
    
    if ($options->exists("success")) {
      $self->{success} = $options->{"success"}->(byte);
    }
    
    if ($options->exists("match_start")) {
      $self->{match_start} = $options->{"match_start"}->(int);
    }
    
    if ($options->exists("match_length")) {
      $self->{match_length} = $options->{"match_length"}->(int);
    }
    
    if ($options->exists("captures")) {
      my $captures = $options->{"captures"}->(string[]);
      $self->{captures} = Array->copy_string_address($captures);
    }
    
    return $self;
  }
  
  private static method _new : Regex::Match ($success : int, $captures : string[], $match_start : int, $match_length : int) {
    my $self = &new({
      success => $success,
      captures => $captures,
      match_start => $match_start,
      match_length => $match_length,
    });
    
    return $self;
  }
  
  # Instance Method
  method captures_length : int () {
    return @{$self->captures};
  }
  
  method cap : string ($index : int) {
    return $self->captures->[$index - 1];
  }
  
  method cap1 : string () { return $self->captures->[0]; }
  
  method cap2 : string () { return $self->captures->[1]; }
  
  method cap3 : string () { return $self->captures->[2]; }
  
  method cap4 : string () { return $self->captures->[3]; }
  
  method cap5 : string () { return $self->captures->[4]; }
  
  method cap6 : string () { return $self->captures->[5]; }
  
  method cap7 : string () { return $self->captures->[6]; }
  
  method cap8 : string () { return $self->captures->[7]; }
  
  method cap9 : string () { return $self->captures->[8]; }
  
  method cap10 : string () { return $self->captures->[9]; }
  
  method cap11 : string () { return $self->captures->[10]; }
  
  method cap12 : string () { return $self->captures->[11]; }
  
  method cap13 : string () { return $self->captures->[12]; }
  
  method cap14 : string () { return $self->captures->[13]; }
  
  method cap15 : string () { return $self->captures->[14]; }
  
  method cap16 : string () { return $self->captures->[15]; }
  
  method cap17 : string () { return $self->captures->[16]; }
  
  method cap18 : string () { return $self->captures->[17]; }
  
  method cap19 : string () { return $self->captures->[18]; }
  
  method cap20 : string () { return $self->captures->[19]; }
  
}
