//
// Copyright (c) 2010, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   20 Mar 10  Brian Frank  Creation
//

**
** CsvOutStream is used to write delimiter-separated values
** as specified by RFC 4180.  Format details:
**   - rows are delimited by a newline
**   - cells are separated by `delimiter` char
**   - cells containing the delimiter, '"' double quote, or
**     newline are quoted; quotes are escaped as '""'
**
** Also see `CsvInStream`.
**
@Js
class CsvOutStream : OutStream
{

  **
  ** Wrap the underlying output stream.
  **
  new make(OutStream out) : super(out) {}

  **
  ** Delimiter character; defaults to comma.
  **
  Int delimiter := ','

  **
  ** Write the row of cells with the configured delimiter.
  ** Also see `writeCell`.
  **
  virtual This writeRow(Str[] row)
  {
    row.each |cell, i|
    {
      if (i > 0) writeChar(delimiter)
      writeCell(cell)
    }
    return writeChar('\n')
  }

  **
  ** Write a single cell.  If `isQuoteRequired` returns true,
  ** then quote it.
  **
  virtual This writeCell(Str cell)
  {
    if (!isQuoteRequired(cell)) return print(cell)
    writeChar('"')
    cell.each |ch|
    {
      if (ch == '"') writeChar('"')
      writeChar(ch)
    }
    return writeChar('"')
  }

  **
  ** Return if the given cell string contains:
  **  - the configured delimiter
  **  - double quote '"' char
  **  - leading/trailing whitespace
  **  - newlines
  **
  Bool isQuoteRequired(Str cell)
  {
    if (cell.isEmpty) return true
    if (cell[0].isSpace || cell[-1].isSpace) return true
    return cell.any |ch| { ch == delimiter || ch == '"' || ch == '\n' || ch == '\r' }
  }

}