class TestCase::Sys::Time {
  use Sys::Time;
  use Sys::Time::Timeval;
  use Sys::Time::Timezone;
  use Sys::Time::Timespec;
  use Sys::Time::Constant as TIME;
  use Sys::Time::Itimerval;
  use Sys::Time::Utimbuf;
  
  static method new_tm : int () {
    my $tm = Sys::Time::Tm->new;
    
    unless ($tm isa Sys::Time::Tm) {
      return 0;
    }
    
    return 1;
  }
  
  static method time : long () {
    my $time = Sys::Time->time;
    
    return $time;
  }
  
  static method localtime : int () {
    {
      my $tm = Sys->localtime(0);
      
      unless ($tm->tm_year + 1900 == 1970) {
        return 0;
      }
    }
    
    {
      my $tm = Sys->localtime;
      
      unless ($tm->tm_year + 1900 > 1970) {
        return 0;
      }
    }
    
    unless (Sys::OS->is_windows) {
      my $tm = Sys->localtime(-(86_400 * 2), 1);
      
      unless ($tm->tm_year + 1900 == 1969) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method localtime_value : Sys::Time::Tm ($time : long) {
    my $time_info = Sys::Time->localtime(\$time);
    
    return $time_info;
  }
  
  static method gmtime : int () {
    {
      my $tm = Sys->gmtime(0);
      
      unless ($tm->tm_year + 1900 == 1970) {
        return 0;
      }
    }
    
    {
      my $tm = Sys->gmtime;
      
      unless ($tm->tm_year + 1900 > 1970) {
        return 0;
      }
    }
    
    unless (Sys::OS->is_windows) {
      my $tm = Sys->gmtime(-(86_400 * 2), 1);
      
      unless ($tm->tm_year + 1900 == 1969) {
        return 0;
      }
    }
    
    return 1;
  }
  
  static method gmtime_value : Sys::Time::Tm ($time : long) {
    my $time_info = Sys::Time->gmtime(\$time);
    
    return $time_info;
  }
  
  static method gettimeofday : int () {
    
    my $tv = Sys::Time::Timeval->new;
    my $tz = Sys::Time::Timezone->new;
    
    my $status = Sys::Time->gettimeofday($tv, $tz);
    
    unless ($status == 0) {
      return 0;
    }
    
    unless ($tv->tv_sec > 0) {
      return 0;
    }
    
    return 1;
  }

  static method clock : int () {
    
    my $tv = Sys::Time::Timeval->new;
    my $tz = Sys::Time::Timezone->new;
    
    my $cpu_time = Sys::Time->clock;
    
    unless ($cpu_time >= 0) {
      return 0;
    }
    
    return 1;
  }
  
  static method clock_gettime : int () {
    
    my $tp = Sys::Time::Timespec->new;
    
    my $status = Sys::Time->clock_gettime(TIME->CLOCK_REALTIME, $tp);
    
    unless ($status >= 0) {
      return 0;
    }
    
    unless ($tp->tv_sec >= 0) {
      return 0;
    }
    
    return 1;
  }
  
  static method clock_getres : int () {
    
    my $tp = Sys::Time::Timespec->new;
    
    my $status = Sys::Time->clock_getres(TIME->CLOCK_REALTIME, $tp);
    
    unless ($status >= 0) {
      return 0;
    }
    
    unless ($tp->tv_sec >= 0) {
      return 0;
    }
    
    return 1;
  }


  static method setitimer : int () {
    
    my $new_tv = Sys::Time::Timeval->new(1, 1);
    
    my $new_value = Sys::Time::Itimerval->new;
    $new_value->set_it_interval($new_tv);
    
    my $old_value = Sys::Time::Itimerval->new;
    
    my $status = Sys::Time->setitimer(TIME->ITIMER_REAL, $new_value, $old_value);
    
    unless ($status == 0) {
      return 0;
    }
    
    return 1;
  }
  
  static method getitimer : int () {
    
    my $curr_value = Sys::Time::Itimerval->new;
    
    my $status = Sys::Time->getitimer(TIME->ITIMER_REAL, $curr_value);
    
    unless ($status == 0) {
      return 0;
    }
    
    return 1;
  }

  static method times : int () {
    
    my $buffer = Sys::Time::Tms->new;
    
    my $tick = Sys::Time->times($buffer);
    
    warn $tick;
    
    unless ($tick >= 0) {
      return 0;
    }

    warn $buffer->tms_utime;
    
    unless ($buffer->tms_utime > 0) {
      return 0;
    }
    
    warn $buffer->tms_stime;
    
    unless ($buffer->tms_stime >= 0) {
      return 0;
    }
    
    warn $buffer->tms_cutime;
    
    unless ($buffer->tms_cutime >= 0) {
      return 0;
    }
    
    warn $buffer->tms_cstime;
    
    unless ($buffer->tms_cstime >= 0) {
      return 0;
    }
    
    # The fields of the Sys::Time::Tms class
    {
      $buffer->set_tms_utime(0);
      $buffer->set_tms_stime(0);
      $buffer->set_tms_cutime(0);
      $buffer->set_tms_cstime(0);
    }
    
    return 1;
  }


  static method clock_nanosleep : int () {
    
    my $start = Sys::Time->time;
    
    my $request = Sys::Time::Timespec->new;
    $request->set_tv_sec(1);
    $request->set_tv_nsec(100_000_000);

    my $remain = Sys::Time::Timespec->new;
    
    my $status = Sys::Time->clock_nanosleep(TIME->CLOCK_REALTIME, 0, $request, $remain);
    
    unless ($status  == 0) {
      return 0;
    }
    
    unless (Sys::Time->time - $start >= 1) {
      return 0;
    }
    
    return 1;
  }

  static method nanosleep : int () {
    
    my $start = Sys::Time->time;
    
    my $ts = Sys::Time::Timespec->new(1, 100_000_000);
    
    my $status = Sys::Time->nanosleep($ts, undef);
    
    unless ($status  == 0) {
      return 0;
    }
    
    unless (Sys::Time->time - $start >= 1) {
      return 0;
    }
    
    return 1;
  }
  
  static method utime : int ($test_dir : string) {
    
    my $file = "$test_dir/ftest/utime.txt";
    
    my $utimbuf = Sys::Time::Utimbuf->new;
    
    my $time = Sys::Time->time;
    
    my $actime = $utimbuf->set_actime($time);
    my $modtime = $utimbuf->set_modtime($time);
    
    my $status = Sys::Time->utime($file, $utimbuf);
    
    unless ($status == 0) {
      return 0;
    }
    
    return 1;
  }
  
  static method utimes : int ($test_dir : string) {
    
    if (Sys::OS->is_windows) {
      eval { Sys::Time->utimes(undef, undef); }
      unless ($@ && eval_error_id is_error Error::NotSupported) {
        return 0;
      }
    }
    else {
      my $file = "$test_dir/ftest/utime.txt";
      
      my $times0 = Sys::Time::Timeval->new;
      Sys::Time->gettimeofday($times0, undef);
      
      my $times1 = Sys::Time::Timeval->new;
      Sys::Time->gettimeofday($times1, undef);
      
      my $times = [$times0, $times1];
      
      my $status = Sys::Time->utimes($file, $times);
      
      unless ($status == 0) {
        return 0;
      }
    }
    
    return 1;
  }
  
}