const _ = require('lodash');
const glob = require('glob');
const fs = require('fs');
const Promise = require('bluebird');
const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin;
const exec = require('child-process-promise').exec;
const webpackModule = require('webpack');

function webpack(config, callback) {
  return webpackModule(config, function(err, stats) {
    if (err || stats.hasErrors()) {
      return callback(err || stats.toJson().errors.join('\n'));
    }
    return callback(null);
  });
}

module.exports = {
  alias: 'assets',
  afterConstruct: function(self) {
    self.servePublicAssets();
  },
  construct: function(self, options) {
    self.addTask('build', 'Build Apostrophe frontend javascript master import file', (apos, argv) => {
      // 1. rsync-like copy of everything to public/apos-modules
      // 2. webpack can glob it, and we can make the export file
      let components = [];
      const seen = {};
      _.each(apos.modules, function(module, name) {
        _.each(module.__meta.chain, function(entry) {
          if (seen[entry.dirname]) {
            return;
          }
          components = components.concat(glob.sync(`${entry.dirname}/src/apos/**/*.vue`));       
          seen[entry.dirname] = true;
        });
      });
      const mapped = components.map(component => {
        const jsFilename = JSON.stringify(component);
        const name = require('path').basename(component).replace(/\.\w+/, '');
        const jsName = JSON.stringify(name);
        return `
import ${name} from ${jsFilename};
Vue.component(${jsName}, ${name});
`
      ;
      }).join('\n');
      const buildDir = `${apos.rootDir}/apos-build`;
      if (!fs.existsSync(buildDir)) {
        fs.mkdirSync(buildDir);
      }
      const importFile = `${buildDir}/import-components.js`;
      fs.writeFileSync(importFile, `
import Vue from 'apostrophe/vue';
${mapped}
`
      );
      return Promise.promisify(webpack)({
        entry: importFile,
        output: {
          path: `${apos.rootDir}/public/apos-frontend`,
          filename: 'user-bundle.js'
        },
        resolve: {
          alias: {
            apostrophe: apos.rootDir + '/node_modules/apostrophe/node_modules'
          }
        },
        stats: 'verbose',
        module: {
          rules: [
            {
              test: /\.vue$/,
              loader: 'vue-loader'
            }
          ]
        },
        plugins: [
          // make sure to include the plugin for the magic
          new VueLoaderPlugin()
        ]
      });
    });

    self.push = function() {};
    self.addHelpers({
      stylesheets: function(when) {
        console.log('TODO do we still need a stylesheets helper');
      },
      scripts: function(when) {
        return self.apos.templates.safe('<script src="/apos-frontend/user-bundle.js"></script>');
      }
    });

    self.servePublicAssets = function() {
      self.expressMiddleware = {
        // Run really early, before all of the stuff apostrophe-express normally
        // puts in, for performance reasons. Preempts expensive
        // queries related to `apostrophe-global` on every static file
        when: 'beforeRequired',
        middleware: self.apos.express.static(
          self.apos.rootDir + '/public',
          self.options.static || {}
        )
      };
    };
  }
};


@@ -162,78 +162,21 @@
 ader
-').VueLoaderPlugin;%0Aconst exec = require('child-process-promise').exec
+/lib/plugin')
 ;%0Aco
@@ -1144,23 +1144,16 @@
 .vue%60));
-       
 %0A       
@@ -1529,16 +1529,18 @@
 %60%0A      
+  
 ;%0A      
@@ -2021,32 +2021,146 @@
 .js'%0A        %7D,%0A
+        resolveLoader: %7B%0A          modules: %5B %60$%7Bapos.rootDir%7D/node_modules/apostrophe/node_modules%60 %5D%0A        %7D,%0A
         resolve:
@@ -2193,16 +2193,17 @@
         
+'
 apostrop
@@ -2204,18 +2204,22 @@
 ostrophe
+'
 : 
+%60$%7B
 apos.roo
@@ -2222,20 +2222,17 @@
 .rootDir
- + '
+%7D
 /node_mo
@@ -2260,17 +2260,17 @@
 _modules
-'
+%60
 %0A       
@@ -3394,9 +3394,8 @@
 %0A  %7D%0A%7D;%0A
-%0A

Resolve loaders to correct node_modules