/*
 * Copyright (c) 2017 Bonnie Schulkin. All Rights Reserved.
 *
 * This file is part of BoxCharter.
 *
 * BoxCharter is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * BoxCharter is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with BoxCharter. If not, see <http://www.gnu.org/licenses/>.
 *
 */

/**
 * Utilities to reset the database in between tests.
 * @module db_reset
 */
const { db } = require('../../../server/src/model/utilities/db_connection')
const { addKeys } = require('../../../server/src/model/data/add_keys')
const { addUser } = require('./test_data/add_user')
const { addEntireChart } = require('./test_data/add_chart')

/**
 * Get all the tables in the current db connection.
 * @function
 * @returns {Promise} - Promise resolving to array of objects each representing
 *  a table. Each object has a key 'table_name'.
 */
const getTables = function () {
  return db.query(
    `SELECT table_name
      FROM information_schema.tables
      WHERE table_schema = 'public';`)
}

/**
 * Truncate all tables to reset the database.
 * @function
 * @returns {Promise} - Promise whose resolution is unimportant.
 */
const resetDB = async function () {
  if (process.env.NODE_ENV === 'production') {
    throw new Error('Cowardly refusing to truncate production db.')
  }
  try {
    const tables = await getTables()
    return await Promise.all(tables.map(table =>
      db.none(`TRUNCATE ${table.table_name} RESTART IDENTITY CASCADE`),
    ))
  } catch (err) {
    console.error(err)
    return null
  }
}

/**
 * Seed the database using functions from the db/seed directory.
 * @function
 * @param {object} options - see initDB JSDoc for description
 * @returns {Promise} - resolution unimportant
 */
const seedDB = (options) => 
  addKeys()
    .then(addUser)
    .then(() => {
      if (!options.omitCharts) addEntireChart()
    })
    .catch(console.error)

/**
 * Initialize the db: both reset it, and then seed it.
 * @function
 * @param {object} options - keys: omitCharts (boolean), whether to add charts
 * @returns {Promise} - resolution unimportant
 */
const initDB = (options) => resetDB().then(() => seedDB(options)).catch(console.error)

// if the file is run as a command (used in npm scripts)
if (!module.parent) {
  const command = process.argv[2]
  switch (command) {
    case 'seed':
      seedDB({})
      break
    case 'reset':
      resetDB()
      break
    default:
      console.error(`${command} is not a valid command`)
  }
}

module.exports = { initDB }

@@ -2071,70 +2071,8 @@
 ion%0A
- * @param %7Bobject%7D options - see initDB JSDoc for description%0A
  * @
@@ -2130,31 +2130,24 @@
 t seedDB = (
-options
 ) =%3E %0A  addK
@@ -2185,47 +2185,8 @@
 hen(
-() =%3E %7B%0A      if (!options.omitCharts) 
 addE
@@ -2199,16 +2199,8 @@
 hart
-()%0A    %7D
 )%0A  
@@ -2300,87 +2300,8 @@
 ion%0A
- * @param %7Bobject%7D options - keys: omitCharts (boolean), whether to add charts%0A
  * @
@@ -2363,23 +2363,30 @@
 itDB = (
-options
+addCharts=true
 ) =%3E res
@@ -2401,29 +2401,14 @@
 hen(
-() =%3E seedDB(options)
+seedDB
 ).ca
@@ -2595,10 +2595,8 @@
 dDB(
-%7B%7D
 )%0A  

Revert db_reset to state where only two tests were failing.