const config = require('config')
const process = require('process')
const semver = require('semver')
const pjson = require('./../../package.json')
const colors = require('colors/safe')
const logger = require('../logger')
const portscanner = require('portscanner')
const path = require('path')
const fs = require('fs-extra')

const validatePreconditions = async ({ exitOnFailure = true } = {}) => {
  let success = true
  success = checkIfRunningOnSupportedNodeVersion(process.version) && success
  success = checkIfRequiredFileExists('../../frontend/dist/frontend/index.html') && success
  success = checkIfRequiredFileExists('../../frontend/dist/frontend/main.js') && success
  success = checkIfRequiredFileExists('../../frontend/dist/frontend/polyfills.js') && success
  success = checkIfRequiredFileExists('../../frontend/dist/frontend/runtime.js') && success
  success = checkIfRequiredFileExists('../../frontend/dist/frontend/vendor.js') && success
  const portSuccess = await checkIfPortIsAvailable(process.env.PORT || config.get('server.port'))

  if ((!success || !portSuccess) && exitOnFailure) {
    logger.error(colors.red('Exiting due to unsatisfied precondition!'))
    process.exit(1)
  }
  return success
}

const checkIfRunningOnSupportedNodeVersion = (runningVersion) => {
  const supportedVersion = pjson.engines.node
  const effectiveVersionRange = semver.validRange(supportedVersion)
  if (!semver.satisfies(runningVersion, effectiveVersionRange)) {
    logger.warn(`Detected Node version ${colors.bold(runningVersion)} is not in the supported version range of ${supportedVersion} (${colors.red('NOT OK')})`)
    return false
  }
  logger.info(`Detected Node.js version ${colors.bold(runningVersion)} (${colors.green('OK')})`)
  return true
}

const checkIfPortIsAvailable = (port) => {
  return new Promise((resolve, reject) => {
    portscanner.checkPortStatus(port, function (error, status) {
      if (error) {
        reject(error)
      } else {
        if (status === 'open') {
          logger.warn(`Port ${colors.bold(port)} is in use (${colors.red('NOT OK')})`)
          resolve(false)
        } else {
          logger.info(`Port ${colors.bold(port)} is available (${colors.green('OK')})`)
          resolve(true)
        }
      }
    })
  })
}

const checkIfRequiredFileExists = (relPath) => {
  const fileName = relPath.substr(relPath.lastIndexOf('/') + 1)
  if (!fs.existsSync(path.resolve(__dirname, relPath))) {
    logger.warn(`Required file ${colors.bold(fileName)} is missing (${colors.red('NOT OK')})`)
    return false
  }
  logger.info(`Required file ${colors.bold(fileName)} is present (${colors.green('OK')})`)
  return true
}

validatePreconditions.checkIfRunningOnSupportedNodeVersion = checkIfRunningOnSupportedNodeVersion
validatePreconditions.checkIfPortIsAvailable = checkIfPortIsAvailable
validatePreconditions.checkIfRequiredFileExists = checkIfRequiredFileExists

module.exports = validatePreconditions

@@ -481,32 +481,167 @@
 ion) && success%0A
+  success = checkIfRunningOnSupportedOS(process.platform) && success%0A  success = checkIfRunningOnSupportedCPU(process.arch) && success%0A
   success = chec
@@ -1888,24 +1888,802 @@
 urn true%0A%7D%0A%0A
+const checkIfRunningOnSupportedOS = (runningOS) =%3E %7B%0A  const supportedOS = pjson.os%0A  if (supportedOS%5BrunningOS%5D %3E -1) %7B%0A    logger.warn(%60Detected OS $%7Bcolors.bold(runningOS)%7D is not in the list of supported platforms $%7BsupportedOS%7D ($%7Bcolors.red('NOT OK')%7D)%60)%0A    return false%0A  %7D%0A  logger.info(%60Detected OS $%7Bcolors.bold(runningOS)%7D ($%7Bcolors.green('OK')%7D)%60)%0A  return true%0A%7D%0A%0Aconst checkIfRunningOnSupportedCPU = (runningArch) =%3E %7B%0A  const supportedArch = pjson.cpu%0A  if (supportedArch%5BrunningArch%5D %3E -1) %7B%0A    logger.warn(%60Detected CPU $%7Bcolors.bold(runningArch)%7D is not in the list of supported architectures $%7BsupportedArch%7D ($%7Bcolors.red('NOT OK')%7D)%60)%0A    return false%0A  %7D%0A  logger.info(%60Detected CPU $%7Bcolors.bold(runningArch)%7D ($%7Bcolors.green('OK')%7D)%60)%0A  return true%0A%7D%0A%0A
 const checkI

Validate OS and CPU on startup