// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

///|
extern "C" fn get_cli_args_ffi() -> FixedArray[@os_string.OsString] = "moonbit_rt_get_cli_args"

///|
fn get_cli_args_internal() -> Array[String] {
  [
    for t in get_cli_args_ffi() => t.to_string()
  ]
}

///|
extern "c" fn exit_internal(code : Int32) -> Unit = "exit"

///|
extern "c" fn now_internal() -> UInt64 = "moonbit_get_ms_since_epoch"

///|
extern "c" fn getcwd() -> @os_string.OsString = "moonbit_rt_get_current_dir"

///|
fn current_dir_internal() -> String? {
  let res = getcwd().to_string()
  // Valid current working directory can never be empty.
  // So the runtime API use empty return value to indicate failure.
  if res is "" {
    None
  } else {
    Some(res)
  }
}

///|
fn get_env_var_internal(key : String) -> String? {
  let key = @os_string.OsString::from_string(key)
  let exists = @ref.Ref(false)
  let value = get_env_var_ffi(key, exists)
  if exists.val {
    Some(value.to_string())
  } else {
    None
  }
}

///|
#borrow(key, exists)
extern "c" fn get_env_var_ffi(
  key : @os_string.OsString,
  exists : @ref.Ref[Bool],
) -> @os_string.OsString = "moonbit_rt_get_env_var"

///|
fn get_env_vars_internal() -> Map[String, String] {
  let env_vars = get_env_vars_ffi()
  let res = Map([])
  for i = 0; i < env_vars.length(); i = i + 2 {
    res[env_vars[i].to_string()] = env_vars[i + 1].to_string()
  }
  res
}

///|
extern "c" fn get_env_vars_ffi() -> FixedArray[@os_string.OsString] = "moonbit_rt_get_env_vars"

///|
fn set_env_var_internal(key : String, value : String) -> Unit {
  set_env_var_ffi(
    @os_string.OsString::from_string(key),
    @os_string.OsString::from_string(value),
  )
}

///|
#borrow(key, value)
extern "c" fn set_env_var_ffi(
  key : @os_string.OsString,
  value : @os_string.OsString,
) -> Unit = "moonbit_rt_set_env_var"

///|
fn unset_env_var_internal(key : String) -> Unit {
  unset_env_var_ffi(@os_string.OsString::from_string(key))
}

///|
#borrow(key)
extern "c" fn unset_env_var_ffi(key : @os_string.OsString) -> Unit = "moonbit_rt_unset_env_var"

///|
fn rand_internal(to_be_filled : FixedArray[Byte]) -> Bool {
  moonbit_rt_get_random(to_be_filled) == 0
}

///|
#borrow(to_be_filled)
extern "c" fn moonbit_rt_get_random(to_be_filled : FixedArray[Byte]) -> Int32 = "moonbit_rt_get_random"