#!/usr/bin/env node

import yargs from 'yargs';
import Client from './Client.js';
import fs from 'fs';
import { killPort, run } from './commands/';
import { fork } from 'child_process';
import { isPortTaken, findFile } from './util';

const DEFAULT_PORT_NUMBER = 5004;
const DEFAULT_NUM_WORKERS = 4;

const start = () => {
  const options = {};
  const usage = `Spins up a server on a specified port to run eslint in parallel.
    Usage: esprint [args]`;

  const argv = yargs
    .usage(usage)
    .command('kill', 'Kills the background server', () => {}, () => {
      killPort();
    })
    .command(['*', 'start'], 'Starts up a background server which listens for file changes. If no port is specified, then runs parallelized eslint with no background server', () => {}, (argv) => {
      const filePath = findFile('.esprintrc');

      if (!filePath) {
        console.error('Unable to find `.esprintrc` file. Exiting...');
        process.exit(0);
      } else {
        const rc = JSON.parse(fs.readFileSync(filePath));
        Object.assign(options, rc);
        Object.assign(options, {rcPath: filePath});

        if (!rc.workers) {
         Object.assign(options, {workers: DEFAULT_NUM_WORKERS});
        }
        if (!rc.port) {
          run(options);
        } else {
          connect(options);
        }
      }
    })
    .help().argv;
};

const connect = (options) => {
  const args = [];
  for (const key in options) {
    args.push(`--${key}=${options[key]}`);
  }

  const port = options.port;

  isPortTaken(port).then(isTaken => {
    // start the server if it isn't running
    const client = new Client(port);

    if (!isTaken) {
      const child = fork(
        require.resolve('./startServer.js'), args, {/* silent: true */}
      );

      child.on('message', message => {
        if (message.server) {
          // Wait for the server to start before connecting
          client.connect();
        } else if (message.message) {
          process.stdout.clearLine();
          process.stdout.cursorTo(0);
          process.stdout.write(message.message);
        }
      });
    } else {
      // Connect anyways
      // TODO(allenk): Actually check that the server is occupying the port
      client.connect();
    }
  });
};

start();

@@ -1020,16 +1020,46 @@
 Path));%0A
+%0A        if (!rc.workers) %7B%0A  
         
@@ -1085,167 +1085,401 @@
 ns, 
-rc);%0A        Object.assign(options, %7BrcPath: filePath%7D);%0A%0A        if (!rc.workers) %7B%0A         Object.assign(options, %7Bworkers: DEFAULT_NUM_WORKERS%7D);%0A        %7D
+%7Bworkers: DEFAULT_NUM_WORKERS%7D);%0A        %7D else if (rc.workers && rc.workers %3E require('os').cpus().length) %7B%0A          conosle.error(%60Cannot use the amount of worker threads specified! Maximum: $%7Brequire('os').cpus().length%7D. Specified: $%7Brc.workers%7D. Exiting...%60);%0A          process.exit(0);%0A        %7D%0A%0A        Object.assign(options, rc);%0A        Object.assign(options, %7BrcPath: filePath%7D);%0A
 %0A   

Throw error when user specifies more worker threads than available cpus (#20)