class TestCase::Sys::IO::Stat {
  use Fn;
  use Sys::IO::Stat;
  use Sys;
  use Sys::IO;
  use Sys::OS;
  
  our $TEST_TMP_DIR : rw cache string;
  
  static method stat : int ($test_dir : string) {
    
    {
      my $file = "$test_dir/ftest/readline_long_lines.txt";
      
      my $stat = Sys::IO::Stat->new;
      my $status = Sys::IO::Stat->stat($file, $stat);
      unless ($status == 0) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir/ftest/not_found.txt";
      
      my $stat = Sys::IO::Stat->new;
      {
        eval { Sys::IO::Stat->stat("$file/not_found.txt", $stat); };
        unless (Fn->contains($@, "not_found.txt")) {
          return 0;
        }
      }
    }
    
    # Accessor methods
    {
      my $file = "$test_dir/ftest/readline_long_lines.txt";
      
      my $stat = Sys::IO::Stat->new;
      Sys::IO::Stat->stat($file, $stat);
      
      unless ($stat->dev == $stat->st_dev) {
        return 0;
      }
      
      unless ($stat->ino == $stat->st_ino) {
        return 0;
      }
      
      unless ($stat->mode == $stat->st_mode) {
        return 0;
      }
      
      unless ($stat->nlink == $stat->st_nlink) {
        return 0;
      }
      
      unless ($stat->uid == $stat->st_uid) {
        return 0;
      }
      
      unless ($stat->gid == $stat->st_gid) {
        return 0;
      }
      
      unless ($stat->rdev == $stat->st_rdev) {
        return 0;
      }
      
      unless ($stat->size == $stat->st_size) {
        return 0;
      }
      
      unless ($stat->mtime == $stat->st_mtime) {
        return 0;
      }
      
      unless ($stat->atime == $stat->st_atime) {
        return 0;
      }
      
      unless ($stat->ctime == $stat->st_ctime) {
        return 0;
      }
      
      unless (Sys::OS->is_windows) {
        unless ($stat->blksize == $stat->st_blksize) {
          return 0;
        }
        
        unless ($stat->blocks == $stat->st_blocks) {
          return 0;
        }
      }
    
    }
    
    {
      my $file = "$TEST_TMP_DIR/stat_あ.txt";
      
      Sys->open([(Sys::IO::FileStream)undef], ">", $file);
      
      my $stat = Sys::IO::Stat->new;
      my $status = Sys::IO::Stat->stat($file, $stat);
      unless ($status == 0) {
        return 0;
      }
    }
    
    return 1;
  }

  static method stat_info : long[] ($test_dir : string) {
    
    my $file = "$test_dir/ftest/readline_long_lines.txt";
    
    my $stat = Sys::IO::Stat->new;
    Sys::IO::Stat->stat($file, $stat);
    
    my $stat_info = [
      (long)$stat->st_dev,
      (long)$stat->st_ino,
      (long)$stat->st_mode,
      (long)$stat->st_nlink,
      (long)$stat->st_uid,
      (long)$stat->st_gid,
      (long)$stat->st_rdev,
      (long)$stat->st_size,
      (long)$stat->st_atime,
      (long)$stat->st_mtime,
      (long)$stat->st_ctime,
      0,
      0,
    ];
    
    warn("[Test Output]stat:" . $stat->st_atime . " " . $stat->st_mtime . " " . $stat->st_ctime);
    
    unless (Sys::OS->is_windows) {
      $stat_info->[11] = (long)$stat->st_blksize;
      $stat_info->[12] = (long)$stat->st_blocks;
    }
    
    return $stat_info;
  }

  static method lstat : int ($test_dir : string) {
    
    {
      my $file = "$test_dir/ftest/readline_long_lines.txt";
      
      my $stat = Sys::IO::Stat->new;
      my $status = Sys::IO::Stat->lstat($file, $stat);
      unless ($status == 0) {
        return 0;
      }
    }

    {
      my $file = "$test_dir/ftest/not_found.txt";
      
      my $stat = Sys::IO::Stat->new;
      {
        eval { Sys::IO::Stat->lstat("$file/not_found.txt", $stat); };
        unless (Fn->contains($@, "not_found.txt")) {
          return 0;
        }
      }
    }
    
    {
      my $file = "$test_dir/ftest/not_found.txt";
      
      my $stat = (Sys::IO::Stat)undef;
      {
        eval { $stat = Sys->lstat("$file/not_found.txt"); };
        unless (Fn->contains($@, "not_found.txt")) {
          return 0;
        }
      }
    }
    
    {
      my $file = "$TEST_TMP_DIR/lstat_あ.txt";
      
      Sys->open([(Sys::IO::FileStream)undef], ">", $file);
      
      my $stat = Sys::IO::Stat->new;
      my $status = Sys::IO::Stat->lstat($file, $stat);
      unless ($status == 0) {
        return 0;
      }
    }
    
    return 1;
  }

  static method lstat_info : long[] ($test_dir : string) {
    
    my $file = "$test_dir/ftest/readline_long_lines.txt";
    
    my $stat = Sys::IO::Stat->new;
    Sys::IO::Stat->lstat($file, $stat);
    
    my $stat_info = [
      (long)$stat->st_dev,
      (long)$stat->st_ino,
      (long)$stat->st_mode,
      (long)$stat->st_nlink,
      (long)$stat->st_uid,
      (long)$stat->st_gid,
      (long)$stat->st_rdev,
      (long)$stat->st_size,
      (long)$stat->st_atime,
      (long)$stat->st_mtime,
      (long)$stat->st_ctime,
      0,
      0,
    ];

    unless (Sys::OS->is_windows) {
      $stat_info->[11] = (long)$stat->st_blksize;
      $stat_info->[12] = (long)$stat->st_blocks;
    }
    
    return $stat_info;
  }

  static method fstat : int ($test_dir : string) {
    
    {
      my $file = "$test_dir/ftest/readline_long_lines.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $stat = Sys::IO::Stat->new;
      my $status = Sys::IO::Stat->fstat(Sys::IO->fileno($stream), $stat);
      unless ($status == 0) {
        return 0;
      }
    }
    
    {
      my $file = "$test_dir/ftest/readline_long_lines.txt";
      my $stream = Sys::IO->fopen($file, "rb");
      
      my $stat = Sys->fstat(Sys::IO->fileno($stream));
      unless ($stat && $stat != undef) {
        return 0;
      }
    }
    
    return 1;
  }

  static method fstat_info : long[] ($test_dir : string) {
    
    my $file = "$test_dir/ftest/readline_long_lines.txt";
    my $stream = Sys::IO->fopen($file, "rb");
    
    my $stat = Sys::IO::Stat->new;
    Sys::IO::Stat->fstat(Sys::IO->fileno($stream), $stat);
    
    my $stat_info = [
      (long)$stat->st_dev,
      (long)$stat->st_ino,
      (long)$stat->st_mode,
      (long)$stat->st_nlink,
      (long)$stat->st_uid,
      (long)$stat->st_gid,
      (long)$stat->st_rdev,
      (long)$stat->st_size,
      (long)$stat->st_atime,
      (long)$stat->st_mtime,
      (long)$stat->st_ctime,
      0,
      0,
    ];
    
    unless (Sys::OS->is_windows) {
      $stat_info->[11] = (long)$stat->st_blksize;
      $stat_info->[12] = (long)$stat->st_blocks;
    }
    
    return $stat_info;
  }
}