module Node

import Prelude

pfunc getArgs uses (arrayToList MkIORes) :  IO (List String) := `(w) => Prelude_MkIORes( Prelude_arrayToList(null, process.argv.slice(1)), w)`
pfunc readFile uses (MkIORes Left Right) : (fn : String) -> IO (Either String String) := `(fn) => (w) => {
  let fs = require('fs')
  let result
  try {
    let content = fs.readFileSync(fn, 'utf8')
    result = Prelude_Right(content)
  } catch (e) {
    result = Prelude_Left(e+'')
  }
  return Prelude_MkIORes(result, w)
}`

-- I wonder if I should automatically `uses` the constructors in the types
pfunc writeFile uses (MkIORes MkUnit) : String → String → IO (Either String Unit) := `(fn, content) => (w) => {
  let fs = require('fs')
  let result
  try {
    fs.writeFileSync(fn, content, 'utf8')
    result = Prelude_Right( Prelude_MkUnit)
  } catch (e) {
      result = Prelude_Left(e+"")
  }
  return Prelude_MkIORes(result, w)
}`

-- maybe System.exit or something, like the original putStrLn msg >> exitFailure
pfunc exitFailure : ∀ a. String → a := `(_, msg) => {
  console.log(msg);
  process.exit(1);
}`

pfunc putStr uses (MkIORes MkUnit): String → IO Unit := `(s) => (w) => {
  let {writeSync} = require('fs');
  let buf = new TextEncoder().encode(s);
  writeSync(1, buf);
  return Prelude_MkIORes(Prelude_MkUnit, w);
}`

pfunc readLine uses (MkIORes Left Right) : IO (Either String String) := `(w) => {
    let {readSync} = require('fs');
    let buf = Buffer.alloc(1024);
    let p = 0
    while (readSync(0, buf, p, 1, null)) {
        if (buf[p++] == 10) return Prelude_MkIORes(Prelude_Right(new TextDecoder().decode(buf.slice(0,p))),w);
        if (p + 10 > buf.length) {
            let tmp = Buffer.alloc(buf.length * 1.5);
            tmp.set(buf);
            buf = tmp;
        }
    }
    return Prelude_MkIORes(Prelude_Left("EOF"));
}`
