# Copyright (c) 2023 Yuki Kimoto
# MIT License

class Native::BasicType : pointer {
  version_from SPVM;

  allow Native::ClassVar;
  allow Native::Field;
  allow Native::Method;
  allow Native::Runtime;
  
  use Native::Runtime;
  use Native::ClassVar;
  use Native::Field;
  use Native::Method;
  use List;
  use Fn;
  
  # Fields
  has runtime : Native::Runtime;
  
  has ref_class_var : Native::ClassVar;
  
  has ref_field : Native::Field;
  
  has ref_method : Native::Method;
  
  has ref_arg : Native::Arg;
  
  # Class Method
  private static method new_with_pointer : Native::BasicType ($pointer : Address, $options : object[] = undef) {
    
    my $self = new Native::BasicType;
    
    Fn->set_pointer($self, $pointer);
    
    return $self;
  }
  
  # Instance Methods
  native method get_id : int ();
  
  native method get_name : string ();
  
  native method get_class_dir : string ();
  
  native method get_class_rel_file : string ();
  
  native method get_parent : Native::BasicType ();
  
  native method get_category : int ();
  
  native method get_version_string : string ();
  
  native method is_pointer : int ();
  
  native method is_anon : int ();
  
  native method get_class_var_by_index : Native::ClassVar ($class_var_index : int);
  
  native method get_class_var_by_name : Native::ClassVar ($class_var_name : string);
  
  native method get_class_vars_length : int ();
  
  native method get_field_by_index : Native::Field ($field_index : int);
  
  native method get_field_by_name : Native::Field ($field_name : string);
  
  native method get_fields_length : int ();
  
  native method get_method_by_index : Native::Method ($method_index : int);
  
  native method get_method_by_name : Native::Method ($method_name : string);
  
  native method get_methods_length : int ();
  
  native method get_anon_basic_type_by_index : Native::BasicType ($anon_basic_type_index : int);
  
  native method get_anon_basic_types_length : int ();
  
  method get_methods : Native::Method[] ($options : object[] = undef) {
    
    my $methods_length = $self->get_methods_length;
    
    my $methods_list = List->new(new Native::Method[0]);
    
    for (my $index = 0; $index < $methods_length; $index++) {
      my $method = $self->get_method_by_index($index);
      $methods_list->push($method);
    }
    
    my $methods = (Native::Method[])$methods_list->to_array;
    
    return $methods;
  }
  
  method get_fields : Native::Field[] ($options : object[] = undef) {
    
    my $fields_length = $self->get_fields_length;
    
    my $fields_list = List->new(new Native::Field[0]);
    
    for (my $index = 0; $index < $fields_length; $index++) {
      my $field = $self->get_field_by_index($index);
      $fields_list->push($field);
    }
    
    my $fields = (Native::Field[])$fields_list->to_array;
    
    return $fields;
  }
  
  method get_class_vars : Native::ClassVar[] ($options : object[] = undef) {
    
    my $class_vars_length = $self->get_class_vars_length;
    
    my $class_vars_list = List->new(new Native::ClassVar[0]);
    
    for (my $index = 0; $index < $class_vars_length; $index++) {
      my $class_var = $self->get_class_var_by_index($index);
      $class_vars_list->push($class_var);
    }
    
    my $class_vars = (Native::ClassVar[])$class_vars_list->to_array;
    
    return $class_vars;
  }
  
  native method get_basic_type_in_version_from : Native::BasicType ();
  
}
