const constants = require('../constants');
const Events = require('./eventsWrapper');

// Override process.chdir so that we have a partial-implementation PWD for Windows
const realChdir = process.chdir;
process.chdir = (...args) => {
  if (!process.env.PWD) {
    process.env.PWD = process.cwd();
  }
  realChdir(...args);
};

class ProcessWrapper {

  /**
   * Class from which process extend. Should not be instantiated alone.
   * Manages the log interception so that all console.* get sent back to the parent process
   * Also creates an Events instance. To use it, just do `this.events.[on|request]`
   *
   * @param {Options}     _options    Nothing for now
   */
  constructor(_options) {
    this.interceptLogs();
    this.events = new Events();

    this.pingParent();
  }

  // Ping parent to see if it is still alive. Otherwise, let's die
  pingParent() {
    const self = this;
    self.retries = 0;
    function error() {
      if (self.retries > 2) {
          self.kill();
          process.exit();
      }
      self.retries++;
    }
    setInterval(() => {
      try {
        let result = self.send({action: 'ping'});
        if (!result) {
          return error();
        }
      } catch (e) {
        error();
      }
    }, 2000);
  }

  interceptLogs() {
    const context = {};
    context.console = console;

    context.console.log = this._log.bind(this, 'log');
    context.console.warn = this._log.bind(this, 'warn');
    context.console.error = this._log.bind(this, 'error');
    context.console.info = this._log.bind(this, 'info');
    context.console.debug = this._log.bind(this, 'debug');
    context.console.trace = this._log.bind(this, 'trace');
    context.console.dir = this._log.bind(this, 'dir');
  }

  _log(type, ...messages) {
    const isHardSource = messages.some(message => {
      return (typeof message === 'string' && message.indexOf('hard-source') > -1);
    });
    if (isHardSource) {
      return;
    }
    this.send({result: constants.process.log, message: messages, type});
  }

  send() {
    if (!process.connected) {
      return false;
    }
    return process.send(...arguments);
  }

  kill() {
    // Should be implemented by derived class
    console.log('Process killed');
  }
}

process.on('exit', () => {
  process.exit(0);
});

module.exports = ProcessWrapper;

const constants = require('../constants');
const Events = require('./eventsWrapper');

// Override process.chdir so that we have a partial-implementation PWD for Windows
const realChdir = process.chdir;
process.chdir = (...args) => {
  if (!process.env.PWD) {
    process.env.PWD = process.cwd();
  }
  realChdir(...args);
};

class ProcessWrapper {

  /**
   * Class from which process extend. Should not be instantiated alone.
   * Manages the log interception so that all console.* get sent back to the parent process
   * Also creates an Events instance. To use it, just do `this.events.[on|request]`
   *
   * @param {Options}     _options    Nothing for now
   */
  constructor(_options) {
    this.interceptLogs();
    this.events = new Events();

    this.pingParent();
  }

  // Ping parent to see if it is still alive. Otherwise, let's die
  pingParent() {
    const self = this;
    self.retries = 0;
    function error() {
      if (self.retries > 2) {
          self.kill();
          process.exit();
      }
      self.retries++;
    }
    setInterval(() => {
      try {
        let result = self.send({action: 'ping'});
        if (!result) {
          return error();
        }
        self.retries = 0;
      } catch (e) {
        error();
      }
    }, 2000);
  }

  interceptLogs() {
    const context = {};
    context.console = console;

    context.console.log = this._log.bind(this, 'log');
    context.console.warn = this._log.bind(this, 'warn');
    context.console.error = this._log.bind(this, 'error');
    context.console.info = this._log.bind(this, 'info');
    context.console.debug = this._log.bind(this, 'debug');
    context.console.trace = this._log.bind(this, 'trace');
    context.console.dir = this._log.bind(this, 'dir');
  }

  _log(type, ...messages) {
    const isHardSource = messages.some(message => {
      return (typeof message === 'string' && message.indexOf('hard-source') > -1);
    });
    if (isHardSource) {
      return;
    }
    this.send({result: constants.process.log, message: messages, type});
  }

  send() {
    if (!process.connected) {
      return false;
    }
    return process.send(...arguments);
  }

  kill() {
    // Should be implemented by derived class
    console.log('Process killed');
  }
}

process.on('exit', () => {
  process.exit(0);
});

module.exports = ProcessWrapper;

reset counter