#!/usr/bin/env node
const path = require("path")
const fs = require("fs")
const csv = require("csv")
const style = require("../src/style").style
let yargs = require("yargs")

yargs.epilog("Copyright github.com/tecfu 2018")

yargs.option("config", {
  describe: "Specify the configuration for your table."
})

yargs.option("csv-delimiter", {
  describe: "Set the field delimiter. One character only.",
  default: ","
})

yargs.option("csv-escape", {
  describe: "Set the escape character. One character only."
})

yargs.option("csv-rowDelimiter", {
  describe: "String used to delimit record rows. You can also use a special constant: \"auto\",\"unix\",\"max\",\"windows\",\"unicode\".",
  default: "\n"
})

yargs.option("format", {
  describe: "Set input data format",
  choices: ["json", "csv"],
  default: "csv"
})

yargs.option("options\u2010\u002A", {
  describe: "Specify an optional setting where * is the setting name. See README.md for a complete list."
})

// run help only at the end
yargs = yargs.help("h").argv

const emitError = function (type, detail) {
  console.log(`
${style(type, "white", "bgRed")}

${detail}`)
  process.exit(1)
}

// note that this is the first run
let alreadyRendered = false
let previousHeight = 0

let dataFormat = "csv"
switch (true) {
  case (typeof yargs.format === "undefined"):
    break
  case (yargs.format.toString().match(/json/i) !== null):
    dataFormat = "json"
    break
  default:
}

// look for individually flagged options-*
const options = {}
Object.keys(yargs).forEach(function (key) {
  const keyParts = key.split("-")
  if (keyParts[0] === "options") {
    options[keyParts[1]] = yargs[key]
  }
})

// look for options passed via config file
let header = []
if (yargs.header) {
  if (!fs.existsSync(path.resolve(yargs.header))) {
    emitError(
      "Invalid file path",
      `Cannot find config file at: ${yargs.header}.`
    )
  }
  // merge with any individually flagged options
  header = require(path.resolve(yargs.header))
}

// because different dataFormats
const runTable = function (header, body) {
  // footer = [],
  const Table = require("../src/factory.js")
  options.terminalAdapter = true
  const t1 = Table(header, body, options)

  // hide cursor
  console.log("\u001b[?25l")

  // wipe existing if already rendered
  if (alreadyRendered) {
    // move cursor up number to the top of the previous print
    // before deleting
    console.log(`\u001b[${previousHeight + 3}A`)

    // delete to end of terminal
    console.log("\u001b[0J")
  } else {
    alreadyRendered = true
  }

  console.log(t1.render())

  // reset the previous height to the height of this output
  // for when we next clear the print
  previousHeight = t1.height
}

const chunks = []
process.stdin.resume()
process.stdin.setEncoding("utf8")
process.stdin.on("data", function (chunk) {
  chunks.push(chunk)
})
process.stdin.on("end", function () {
  const stdin = chunks.join("")

  // handle dataFormats
  switch (true) {
    case (dataFormat === "json"):
      let data
      try {
        data = JSON.parse(stdin)
      } catch (e) {
        emitError(
          "JSON parse error",
          "Please check to make sure that your input data consists of JSON or specify a different format with the --format flag."
        )
      }
      runTable(header, data)
      break
    default:
      const formatterOptions = {}
      Object.keys(yargs).forEach(function (key) {
        if (key.slice(0, 4) === "csv-" && typeof (yargs[key]) !== "undefined") {
          formatterOptions[key.slice(4)] = yargs[key]
        }
      })

      csv.parse(stdin, formatterOptions, function (err, data) {
      // validate csv
        if (err || typeof data === "undefined") {
          emitError(
            "CSV parse error",
            "Please check to make sure that your input data consists of valid comma separated values or specify a different format with the --format flag."
          )
        }
        runTable(header, data)
      })
  }
})

/* istanbul ignore next */
if (process.platform === "win32") {
  const rl = require("readline").createInterface({
    input: process.stdin,
    output: process.stdout
  })

  rl.on("SIGINT", function () {
    process.emit("SIGINT")
  })
}

/* istanbul ignore next */
process.on("SIGINT", function () {
  // graceful shutdown
  process.exit()
})

process.on("exit", function () {
  // show cursor
  console.log("\u001b[?25h")
})
