///|
fn reverse_line(data : Bytes) -> Bytes {
  let output : Array[Byte] = []
  let mut index = data.length()
  while index > 0 {
    index -= 1
    output.push(data[index])
  }
  Bytes::from_array(output)
}

///|
fn reverse_lines(data : Bytes) -> Bytes {
  let output : Array[Byte] = []
  let mut start = 0
  for index, byte in data {
    if byte == b'\n' {
      output.append(reverse_line(data[start:index].to_owned()).to_array())
      output.push(b'\n')
      start = index + 1
    }
  }
  if start < data.length() {
    output.append(reverse_line(data[start:].to_owned()).to_array())
  }
  Bytes::from_array(output)
}

///|
fn help_message() -> String {
  let message =
    #|Usage: rev [OPTION]... [FILE]...
    #|
    #|Reverse the characters of every line from standard input or one file.
    #|This implementation uses C-locale byte order and preserves line feeds.
    #|      --help               Show this help message.
  message
}

///|
async fn main {
  let parsed = @cli.parse(@env.args()[1:], [@cli.flag("help")]) catch {
    @cli.CliError(option~, message~, ..) => {
      @stdio.stderr.write("rev: \{message}: '\{option}'\n")
      @sys.exit(2)
      return
    }
  }
  if parsed.contains("help") {
    @stdio.stdout.write(help_message() + "\n")
    return
  }
  if parsed.operands.length() > 1 {
    @stdio.stderr.write("rev: multiple input files are not supported\n")
    @sys.exit(2)
    return
  }
  let path = if parsed.operands.is_empty() { "-" } else { parsed.operands[0] }
  let data = try {
    if path == "-" {
      @stdio.stdin.read_all().binary()
    } else {
      @fs.read_file(path).binary()
    }
  } catch {
    err => {
      @stdio.stderr.write("rev: \{err}\n")
      @sys.exit(1)
      return
    }
  }
  @stdio.stdout.write(reverse_lines(data))
}