'use strict';

const n = require('numeric');
const regression = require('./regression');
const numeric = require('numeric');
const get = require('lodash/get');
const fs = require('fs');
const FreeSurfer = require('freesurfer-parser');

module.exports = {
  addBias(A) {
    const tPose = n.transpose(A);
    const withBias = tPose.concat([n.rep([n.dim(A)[0]], 1)]);
    return n.transpose(withBias);
  },

  preprocess(opts) {
    const userData = opts.userData;
    // do some file parsing. here, we're actually using pre-processed data...
    // so just add some bias and bail!
    const result = {};
    const X = userData.files
    .map((file) => fs.readFileSync(file.filename).toString())
    .map((strSurf) => new FreeSurfer({ string: strSurf }))
    .map((surf) => surf.TotalGrayVol); // <== feature to assess!
    result.biasedX = this.addBias(n.transpose([X]));
    result.y = userData.files.map((file) => (file.tags.isControl ? 1 : -1));
    result.lambda = userData.lamba || 0.0;
    result.eta = userData.eta || 1e-1;
    result.numFeatures = numeric.dim(result.biasedX)[1];
    console.log(result);
    return result;
  },

  // @TODO assert proper array dims
  run(opts) {
    const result = opts.previousData;
    const remoteData = get(opts, 'remoteResult.data');

    // clean unused initial data from preprocessing step.
    delete result.lambda;
    delete result.kickoff;
    delete result.eta;
    delete result.numFeatures;

    // begin processing
    result.lGrad = regression.gradient(
      remoteData.currW,
      result.biasedX,
      result.y,
      remoteData.lambda
    );
    result.lObj = regression.objective(
      remoteData.currW,
      result.biasedX,
      result.y,
      remoteData.lambda
    );
    console.log(`gradient: ${result.lGrad}, objective: ${result.lObj}`);
    return result;
  },
};

@@ -405,26 +405,1017 @@
 %0A%0A  
-preprocess(opts) %7B
+/**%0A   * Pre-process.%0A   *%0A   * @param %7BObject%7D opts%0A   * @param %7BRemoteComputationResult%7D opts.remoteResult%0A   * @param %7BProject%7D opts.userData%0A   * @returns %7BObject%7D%0A   */%0A  preprocess(opts) %7B%0A    const features = get(opts, 'remoteResult.pluginState.inputs%5B0%5D%5B0%5D');%0A%0A    if (!features %7C%7C !Array.isArray(features) %7C%7C !features.length) %7B%0A      throw new Error('Expected inputs containing features');%0A    %7D else if (%0A      features.some(f =%3E FreeSurfer.validFields.indexOf(f) %3C 0)%0A    ) %7B%0A      throw new Error(%60Unknown FreeSurfer region in inputs: $%7Bfeatures.toString()%7D%60);%0A    %7D%0A%0A    /**%0A     * @todo: This uses only one feature. Change to use multiple!%0A     *%0A     * @param %7BFreeSurfer%7D freeSurfer%0A     * @returns %7BNumber%7D%0A     */%0A    function pickFeatures(freeSurfer) %7B%0A      return freeSurfer%5Bfeatures%5B0%5D%5D;%0A%0A      // return Object.keys(freeSurfer).reduce((memo, key) =%3E %7B%0A      //   return features.indexOf(key) %3E -1 ?%0A      //     memo.concat(freeSurfer%5Bkey%5D) :%0A      //     memo;%0A      // %7D, %5B%5D);%0A    %7D%0A
 %0A   
@@ -1619,27 +1619,74 @@
 iles
-%0A    
 .map(
-(
 file
-)
  =%3E
+ %7B%0A      const surf = new FreeSurfer(%7B%0A        string:
  fs.
@@ -1727,122 +1727,43 @@
 ng()
-)
+,
 %0A    
-.map((strSurf) =%3E new FreeSurfer(%7B string: strSurf %7D))
+  %7D);%0A
 %0A    
-.map((surf) =%3E surf.TotalGrayVol); // %3C==
+  // Pluck
  feature
  to 
@@ -1758,16 +1758,17 @@
  feature
+s
  to asse
@@ -1769,17 +1769,57 @@
 o assess
-!
+%0A      return pickFeatures(surf);%0A    %7D);
 %0A    res

Implement input feature selection in pre-processing.