import { spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
import createBus from 'resolve-bus';
import driverRabbitmq from 'resolve-bus-rabbitmq';
import driverZmq from 'resolve-bus-zmq';

import config from './config';

const POINTS = config.BENCHMARK_SERIES;

const busRabbitmq = createBus({ driver: driverRabbitmq({
    url: config.RABBITMQ_CONNECTION_URL
}) });

const busZmq = createBus({ driver: driverZmq({
    address: config.ZMQ_HOST,
    pubPort: config.ZMQ_PUB_PORT,
    subPort: config.ZMQ_SUB_PORT
}) });

function getRabbitmqHelper(eventCount) {
    return {
        spawner: spawn('babel-node', [path.join(__dirname, './readEventsRabbit'), eventCount]),
        emitter: event => busRabbitmq.emitEvent(event)
    };
}

function getZmqHelper(eventCount) {
    return {
        spawner: spawn('babel-node', [path.join(__dirname, './readEventsZmq'), eventCount]),
        emitter: event => busZmq.emitEvent(event)
    };
}

function generateEvent() {
    return {
        type: 'EVENT_TYPE',
        payload: {}
    };
}

function runLoadTests(helper) {
    const child = helper.launcher();
    const initialTime = +new Date();
    let consoleInfo = '';
    let isDone = false;

    let resolver;
    const done = new Promise((resolve, reject) => (resolver = resolve));

    const logHandler = rawData => (consoleInfo += rawData.toString('utf8'));

    const doneHandler = () => {
        const workTime = +new Date() - initialTime;
        const passedInfo = JSON.parse(consoleInfo);
        resolver({ ...passedInfo, time: workTime });
        isDone = true;
    };

    child.stdout.on('data', logHandler);
    child.stderr.on('data', logHandler);
    child.on('exit', doneHandler);

    const produceEventsAsync = () => {
        if (isDone) return;
        helper.emitter(generateEvent());
        setImmediate(produceEventsAsync);
    }

    produceEventsAsync();
    return done;
}

function fsWriteFileAsync(filename, content) {
    return new Promise((resolve, reject) =>
        fs.writeFile(filename, content, (err, value) => (
            !err ? resolve(value) : reject(err)
        ))
    );
}

function generateEvents(arr, i, storage) {
    const eventCount = arr[i];

    return runLoadTests(getRabbitmqHelper(eventCount))
        .then(rabbit => runLoadTests(getZmqHelper(eventCount))
            .then(zmq => (storage[eventCount] = { rabbit, zmq }))
        )
        .then(() => (i < arr.length - 1)
            ? generateEvents(arr, i + 1, storage)
            : storage
        );
}

generateEvents(POINTS, 0, {})
    .then(result => fsWriteFileAsync('./result.json', JSON.stringify(result)))
    .then(() => process.exit(0))
    .catch((err) => {
        // eslint-disable-next-line no-console
        console.log(err);
        process.exit(1);
    });

@@ -596,32 +596,39 @@
 n %7B%0A        
-spawner:
+launcher: () =%3E
  spawn('babe
@@ -629,32 +629,45 @@
 ('babel-node', %5B
+%0A            
 path.join(__dirn
@@ -696,32 +696,41 @@
 it'), eventCount
+%0A        
 %5D),%0A        emit
@@ -843,16 +843,23 @@
     
-spawner:
+launcher: () =%3E
  spa
@@ -876,16 +876,29 @@
 node', %5B
+%0A            
 path.joi
@@ -940,16 +940,25 @@
 entCount
+%0A        
 %5D),%0A    
@@ -1315,33 +1315,23 @@
 Promise(
-(
 resolve
-, reject)
  =%3E (res

Refactor rabbit-zmq load tests