class TestCase::Operator::FieldAccess {
  use TestCase;
  use TestCase::Minimal;
  use TestCase::Simple;
  
  use Fn;
  use Array;
  
  has INT32_MAX : int;
  has next : int;
  has x : int;
  
  static method FLOAT_PRECICE : float () { return 16384.5f; }
  static method DOUBLE_PRECICE : double () { return 65536.5; }
  
  static method get_and_set_field_same_name_as_keyword : int () {
    my $self = new TestCase::Operator::FieldAccess;
    $self->{next} = 1;
    
    unless ($self->{next} == 1) {
      return 0;
    }
    
    return 1;
  }
  
  static method get_field_chain : int () {
    {
      my $simple = TestCase::Simple->new;
      my $minimal = TestCase::Minimal->new;
      $minimal->set_x(5);
      $simple->set_minimal($minimal);
      
      my $x = $simple->minimal->x;
      
      unless ($x == 5) {
        return 0;
      }
    }
    
    {
      my $minimal = TestCase::Minimal->new;
      my $new_minimal = TestCase::Minimal->new;
      
      $minimal->set_x(3);
      $minimal->set_y(5);
      
      $new_minimal->set_x($minimal->y);
      $new_minimal->set_y($minimal->x);
      
      unless ($new_minimal->x == 5) {
        return 0;
      }
      
      unless ($new_minimal->y == 3) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method core_func_name_field_name : int () {
    my $self = new TestCase::Operator::FieldAccess;
    $self->{INT32_MAX} = 1;
    
    unless ($self->{INT32_MAX} == 1) {
      return 0;
    }
    
    return 1;
  }

  # object field is initialized zero
  static method object_field_initialized_zero : int () {
    my $obj = TestCase->new;
    unless ($obj->{x_byte} == 0) {
      return 0;
    }
    unless ($obj->{x_int} == 0) {
      return 0;
    }
    unless ($obj->{x_byte_array} == undef) {
      return 0;
    }
    return 1;
  }

  # object field set and get
  static method object_field : int () {
    my $test_case =TestCase->new;
    
    $test_case->{x_byte} = Fn->INT8_MAX;
    $test_case->{x_short} = Fn->INT16_MAX;
    $test_case->{x_int} = Fn->INT32_MAX;
    $test_case->{x_long} = Fn->INT64_MAX;
    $test_case->{x_float} = TestCase->FLOAT_PRECICE();
    $test_case->{x_double} = TestCase->DOUBLE_PRECICE();
    my $minimal = TestCase::Minimal->new();
    $minimal->{x} = 3;
    $test_case->{minimal} = $minimal;
    
    unless ($test_case->{x_byte} == Fn->INT8_MAX) {
      return 0;
    }
    unless ($test_case->{x_short} == Fn->INT16_MAX) {
      return 0;
    }
    unless ($test_case->{x_int} == Fn->INT32_MAX) {
      return 0;
    }
    unless ($test_case->{x_long} == Fn->INT64_MAX) {
      return 0;
    }
    unless ($test_case->{x_float} == TestCase->FLOAT_PRECICE()) {
      return 0;
    }
    unless ($test_case->{x_double} == TestCase->DOUBLE_PRECICE()) {
      return 0;
    }
    unless ($test_case->{minimal}->{x} == 3) {
      return 0;
    }
    return 1;
  }

  # object field set and get
  static method object_field_again : int () {
    my $test_case =TestCase->new;
    
    $test_case->{x_byte} = Fn->INT8_MAX;
    $test_case->{x_short} = Fn->INT16_MAX;
    $test_case->{x_int} = Fn->INT32_MAX;
    $test_case->{x_long} = Fn->INT64_MAX;
    $test_case->{x_float} = &FLOAT_PRECICE();
    $test_case->{x_double} = &DOUBLE_PRECICE();
    my $minimal = TestCase::Minimal->new();
    $minimal->{x} = 3;
    $test_case->{minimal} = $minimal;

    $test_case->{x_byte} = Fn->INT8_MAX;
    $test_case->{x_short} = Fn->INT16_MAX;
    $test_case->{x_int} = Fn->INT32_MAX;
    $test_case->{x_long} = Fn->INT64_MAX;
    $test_case->{x_float} = &FLOAT_PRECICE();
    $test_case->{x_double} = &DOUBLE_PRECICE();
    $test_case->{minimal} = $minimal;

    unless ($test_case->{x_byte} == Fn->INT8_MAX) {
      return 0;
    }
    unless ($test_case->{x_short} == Fn->INT16_MAX) {
      return 0;
    }
    unless ($test_case->{x_int} == Fn->INT32_MAX) {
      return 0;
    }
    unless ($test_case->{x_long} == Fn->INT64_MAX) {
      return 0;
    }
    unless ($test_case->{x_float} == &FLOAT_PRECICE()) {
      return 0;
    }
    unless ($test_case->{x_double} == &DOUBLE_PRECICE()) {
      return 0;
    }
    unless ($test_case->{minimal}->{x} == 3) {
      return 0;
    }
    
    return 1;
  }
  
  static method exception : int () {
    my $self = (TestCase::Operator::FieldAccess)undef;
    
    eval { $self->{x}; }
    
    unless (Fn->contains($@, "An field access failed. The invocant must be defined.")) {
      return 0;
    }
    
    return 1;
  }
  
}
