'use strict';


const babel     = require('@babel/core');
const _         = require('lodash');
const path      = require('path');


const wrappers = {
  __default__: `
(function () {
  let template = COMPILED_ASSET;
  N.views['<%= apiPath %>'] = (locals, helpers) =>
    template(Object.assign({}, locals, helpers));
})();
`,

  '.pug': `
(function () {
  let pug = require('pug-runtime');
  let template = COMPILED_ASSET;
  N.views['<%= apiPath %>'] = (locals, helpers) =>
    template(Object.assign({}, locals, helpers));
})();
`,

  '.hbs': `
(function () {
  let template = COMPILED_ASSET;
  N.views['<%= apiPath %>'] = (locals, helpers) => {
    let handlebars = require('handlebars/runtime').create();
    for (let name in helpers) {
      // only support helpers in the form of {{fn "argument" a="value1" b="value2"}},
      // i.e. first argument is a string, second is a hash
      handlebars.registerHelper(name, function (str, options) {
        return helpers[name](str, options.hash);
      });
    }
    return handlebars.template(template)(locals);
  };
})();
`
};

// Injections with helpers for template functions
const before = {};
const after = {};

for (let [ type, value ] of Object.entries(wrappers)) {
  let [ beforeTpl, afterTpl ] = value.split('COMPILED_ASSET');
  before[type] = _.template(beforeTpl);
  after[type]  = _.template(afterTpl);
}


function babelify_plugin(context) {
  return Promise.resolve().then(() => {
    let options = {
      presets: [ '@babel/preset-env' ]
    };

    // Source maps are disabled here for performance reasons
    // + old babel source-map version may not support our indexed maps yet
    /*if (context.bundler.sourceMaps) {
      options.inputSourceMap = context.asset.sourceMap || undefined;
      options.sourceFileName = context.asset.sourceMapPath;
      options.sourceMaps = true;
    }*/

    let result = babel.transformSync(context.asset.source, options);

    context.asset.source = result.code;
    context.asset.sourceMap = result.map;
  });
}


module.exports = function (sandbox) {
  _.forEach(sandbox.config.packages, (pkg, pkg_name) => {
    _.forEach(pkg.files.widget_view, file_info => {
      let ext        = path.extname(file_info.path);

      let wrapBefore = before[ext] || before.__default__;
      let wrapAfter  = after[ext]  || after.__default__;

      let asset = sandbox.bundler.createClass('file', {
        logicalPath: file_info.path,
        virtual: true,
        plugins: [ 'load_text', 'macros', 'auto', 'wrapper', babelify_plugin ]
                   .concat(sandbox.compression ? [ 'terser' ] : []),
        wrapBefore: wrapBefore({ apiPath: file_info.api_path }),
        wrapAfter:  wrapAfter({ apiPath: file_info.api_path })
      });

      if (file_info.public) {
        sandbox.component_client[pkg_name].views.push(asset);
      }

      sandbox.component_server[pkg_name].views.push(asset);
    });
  });
};

@@ -295,36 +295,215 @@
 %7B%7D, 
-locals, helpers));%0A%7D)();%0A%60,%0A
+helpers, locals));%0A%7D)();%0A%60,%0A%0A  // for pug partials %60helpers%60 object includes previous locals (merged here previously),%0A  // so we need to assign locals after helpers in case old and new locals have same keys
 %0A  '
@@ -677,30 +677,30 @@
 ign(%7B%7D, 
-locals, helper
+helpers, local
 s));%0A%7D)(

Fix locals merge order in templates