/**
 * These tests help to experiment with the architecture for
 * building pipelines from components.
 */

'use strict';
require('chai').should();

const h = require('highland');

/**
 * In Beam parlance the data source is an input collection, to which things
 * are applied:
 *
 *  new InputCollection([1, 2, 3, 4])
 *  .apply(Doto(element => {
 *    console.log(`Got an element: ${JSON.stringify(element)}`);
 *  }))
 *  ;
 *
 * This would mean that everything has to have an apply() method, since it
 * will be invoked in a standard way from the framework.
 *
 * The advantage of this approach is that it's quite easy to make
 * extensions to the library, by implementing a bunch of classes
 * that have an apply() method. It also means that the extensions
 * could be applied to any library not just Highland.
 */

class InputCollection {
  constructor(source) {
    this._input = source;
  }

  apply(fn) {

    /**
     * If this is the first time through, initialise the pipeline:
     */

    this._pipeline = this._pipeline || this._input;

    /**
     * Now just call the curried function with the current pipeline
     * as input:
     */

    this._pipeline = fn(this._pipeline);
    return this;
  }
};

describe('InputCollection', () => {
  it('simple input', (done) => {
    new InputCollection([1, 2, 3, 4])
    .apply(h.map(element => element * 2))
    .apply(h.collect())
    .apply(h.doto(ar => {
      ar.should.eql([
        1 * 2,
        2 * 2,
        3 * 2,
        4 * 2
      ]);
    }))
    .apply(h.done(done))
    ;
  });

  it('can be reused', (done) => {
    new InputCollection([3, 6, 9, 12])
    .apply(h.map(element => element * 4))
    .apply(h.map(element => element + 2))
    .apply(h.collect())
    .apply(h.doto(ar => {
      ar.should.eql([
        (3 * 4) + 2,
        (6 * 4) + 2,
        (9 * 4) + 2,
        (12 * 4) + 2
      ]);
    }))
    .apply(h.done(done))
    ;
  });
});

@@ -1916,12 +1916,864 @@
 ;%0A  %7D);%0A%7D);%0A
+%0A%0A/**%0A * The top-level component is a Pipeline, which runs against transforms%0A * by using its apply() method.%0A */%0A%0Aclass Pipeline %7B%0A  constructor() %7B%0A    this._input = h();%0A  %7D%0A%0A  apply(fn) %7B%0A%0A    /**%0A     * If this is the first time through, initialise the pipeline:%0A     */%0A%0A    this._pipeline = this._pipeline %7C%7C this._input;%0A%0A    /**%0A     * Now just call the curried function with the current pipeline%0A     * as input:%0A     */%0A%0A    this._pipeline = fn(this._pipeline);%0A    return this;%0A  %7D%0A%7D;%0A%0Adescribe('Pipeline', () =%3E %7B%0A  it('Highland input', (done) =%3E %7B%0A    new Pipeline()%0A    .apply(h.through(h(%5B4, 3, 2, 1%5D)))%0A    .apply(h.map(element =%3E element * 7))%0A    .apply(h.collect())%0A    .apply(h.doto(ar =%3E %7B%0A      ar.should.eql(%5B%0A        4 * 7,%0A        3 * 7,%0A        2 * 7,%0A        1 * 7%0A      %5D);%0A    %7D))%0A    .apply(h.done(done))%0A    ;%0A  %7D);%0A%7D);%0A

add initial version of Pipeline with Highland input