// time module: sleep + time/date helpers

fn sleep(sec:int) -> int:
  if sec < 0:
    ret 0
  ret sleep_ms(sec * 1000)

fn now() -> int:
  ret time_now()

fn now_ms() -> int:
  ret time_now_ms()

fn now_ns() -> int:
  ret time_now_ns()

fn _time_digit(n:int) -> char:
  ret (48 + n) as char

fn _time_is_digit_code(c:int) -> int:
  if c >= 48 && c <= 57:
    ret 1
  ret 0

fn _time_is_date19_at(s:str, off:int) -> int:
  if s == 0 || off < 0:
    ret 0
  if len(s) < off + 19:
    ret 0
  unsafe:
    if _time_is_digit_code((s as *char)[off] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 1] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 2] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 3] as int) == 0:
      ret 0
    if (s as *char)[off + 4] != 45 as char:
      ret 0
    if _time_is_digit_code((s as *char)[off + 5] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 6] as int) == 0:
      ret 0
    if (s as *char)[off + 7] != 45 as char:
      ret 0
    if _time_is_digit_code((s as *char)[off + 8] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 9] as int) == 0:
      ret 0
    if (s as *char)[off + 10] != 32 as char:
      ret 0
    if _time_is_digit_code((s as *char)[off + 11] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 12] as int) == 0:
      ret 0
    if (s as *char)[off + 13] != 58 as char:
      ret 0
    if _time_is_digit_code((s as *char)[off + 14] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 15] as int) == 0:
      ret 0
    if (s as *char)[off + 16] != 58 as char:
      ret 0
    if _time_is_digit_code((s as *char)[off + 17] as int) == 0:
      ret 0
    if _time_is_digit_code((s as *char)[off + 18] as int) == 0:
      ret 0
  ret 1

fn _time_copy_date19(s:str, off:int) -> str:
  if _time_is_date19_at(s, off) == 0:
    ret 0 as str
  out:*char = malloc(20)
  if out == 0:
    ret 0 as str
  i:int = 0
  while i < 19:
    unsafe:
      out[i] = (s as *char)[off + i]
    i = i + 1
  unsafe:
    out[19] = 0 as char
  ret out as str

fn _time_date19_from_output(cmd:str) -> str:
  raw:str = proc_out(cmd)
  if raw == 0:
    ret 0 as str
  out:str = _time_copy_date19(raw, 0)
  unsafe:
    free(raw)
  ret out

fn _time_put2(out:*char, off:int, n:int) -> int:
  if out == 0:
    ret 0
  if n < 0:
    n = 0
  unsafe:
    out[off] = _time_digit((n / 10) % 10)
    out[off + 1] = _time_digit(n % 10)
  ret 0

fn _time_put4(out:*char, off:int, n:int) -> int:
  if out == 0:
    ret 0
  if n < 0:
    n = 0
  unsafe:
    out[off] = _time_digit((n / 1000) % 10)
    out[off + 1] = _time_digit((n / 100) % 10)
    out[off + 2] = _time_digit((n / 10) % 10)
    out[off + 3] = _time_digit(n % 10)
  ret 0

fn _time_format_utc_from_unix(sec:int) -> str:
  if sec < 0:
    sec = 0

  days:int = sec / 86400
  rem:int = sec - (days * 86400)
  hour:int = rem / 3600
  rem = rem - (hour * 3600)
  minute:int = rem / 60
  second:int = rem - (minute * 60)

  z:int = days + 719468
  era:int = z / 146097
  doe:int = z - (era * 146097)
  yoe:int = (doe - (doe / 1460) + (doe / 36524) - (doe / 146096)) / 365
  year:int = yoe + (era * 400)
  doy:int = doe - ((365 * yoe) + (yoe / 4) - (yoe / 100))
  mp:int = ((5 * doy) + 2) / 153
  day:int = doy - (((153 * mp) + 2) / 5) + 1
  month:int = mp + 3
  if mp >= 10:
    month = mp - 9
  if month <= 2:
    year = year + 1

  out:*char = malloc(20)
  if out == 0:
    ret 0 as str

  _time_put4(out, 0, year)
  unsafe:
    out[4] = 45 as char
  _time_put2(out, 5, month)
  unsafe:
    out[7] = 45 as char
  _time_put2(out, 8, day)
  unsafe:
    out[10] = 32 as char
  _time_put2(out, 11, hour)
  unsafe:
    out[13] = 58 as char
  _time_put2(out, 14, minute)
  unsafe:
    out[16] = 58 as char
  _time_put2(out, 17, second)
  unsafe:
    out[19] = 0 as char
  ret out as str

fn date_local() -> str:
  raw:str = date_now()
  if _time_is_date19_at(raw, 0) != 0:
    ret raw

  out:str = _time_date19_from_output("date '+%Y-%m-%d %H:%M:%S'")
  if out != 0:
    ret out

  out = _time_date19_from_output("powershell -NoProfile -Command \"Get-Date -Format 'yyyy-MM-dd HH:mm:ss'\"")
  if out != 0:
    ret out

  ret date_utc()

fn date_utc() -> str:
  ret _time_format_utc_from_unix(now())
