const fs = require('fs');
const stream = require('stream');

const browserify = require('browserify');


class CommonJSTransform extends stream.Transform {
  constructor(path) {
    super();

    this._path = path;

    this._buffer = '';
    this._isFirstLine = true;
  }

  _transform(chunk, encoding, callback) {
    if (this._isFirstLine) {
      this._buffer += chunk.toString();

      if (this._buffer.indexOf('\n') !== -1) {
        this._buffer = this._buffer.replace(/^require=/, 'export default ');
        this._isFirstLine = false;
      }

      callback();
    } else {
      callback(null, this._buffer);
      this._buffer = chunk.toString();
    }
  }

  _flush(callback) {
    callback(null, `${this._buffer.slice(0, -2)}('${this._path}');`);
  }
}


class GlobalObjectTransform extends stream.PassThrough {
  constructor(object) {
    super();

    this._object = object;
  }

  _flush(callback) {
    this.push(`;export default ${this._object};`);
    callback();
  }
}


function esmify(path, { output = process.stdout, object } = {}) {
  const readStream = object
    ? fs.createReadStream(require.resolve(path))
    : browserify().require(path).bundle();

  const tansformStream = object
    ? new GlobalObjectTransform(object)
    : new CommonJSTransform(path);

  const writeStream = typeof output === 'string'
    ? fs.createWriteStream(output)
    : output;

  readStream.pipe(tansformStream).pipe(writeStream);
}


module.exports = {
  esmify,
};
