/* eslint-env node */
/* globals require */
var EmberApp = require('ember-cli/lib/broccoli/ember-app');
var mergeTrees = require('broccoli-merge-trees');
var funnel = require('broccoli-funnel');
var AssetRev = require('broccoli-asset-rev');
var environment = require('./config/environment');
var featuresBuilds = require('./config/features');
var fs = require('fs');
var path = require('path');

var env = EmberApp.env();
module.exports.env = env;

var _buildApp = function (defaults, _trees) {
  var config = environment(env);
  var relativeUrls = config.remoteHostports;

  var trees = _trees || {};

  var app = new EmberApp(defaults, {
    vendorFiles: {
      'jquery.js': false
    },
    storeConfigInMeta: false,
    trees: trees,
    fingerprint: {enabled: false},
    hinting: false,
    template: {
      data: relativeUrls
    },
    babel: {
      // The transpilation of for-of requires Symbol, which is not supported
      // on IE and some valid mobile versions. Thus we disable it here, usage
      // will result in a syntax error on unsupported platforms.
      blacklist: ['es6.forOf']
    }
  });

  // Save off original implementation of the `concatFiles` hook
  var originalConcatFiles = app.concatFiles;

  app.concatFiles = function(tree, options) {
    if (options.annotation === 'Concat: App') {

      var allFeatureFiles = _allFeatureFilesToStripFromApp(app, tree);

      // Exclude modules that should be removed from the build.
      var appTree = funnel(tree, {
        exclude: allFeatureFiles
      });

      // Concat the main app files.
      var concattedAppTree = originalConcatFiles.call(app, appTree, options);

      var concattedFeaturesTree = _buildFeatureFiles(app, tree, originalConcatFiles);

      return mergeTrees([concattedAppTree, concattedFeaturesTree].filter(Boolean));
    }

    return originalConcatFiles.apply(this, arguments);
  };

  app.options.minifyJS.enabled = app.env === 'production';

  // Use `app.import` to add additional libraries to the generated
  // output files.
  //
  // If you need to use different assets in different
  // environments, specify an object as the first parameter. That
  // object's keys should be the environment name and the values
  // should be the asset to use in that environment.
  //
  // If the library that you are including contains AMD or ES6
  // modules that you would like to import into your application
  // please specify an object with the list of modules as keys
  // along with the exports of each module as its value.

  app.import('bower_components/store-js/store.min.js');

  app.import('bower_components/rollbar/dist/rollbar.js');

  app.import('bower_components/client-event-reporter/dist/client-event-reporter.amd.js');

  app.import('bower_components/mousetrap/mousetrap.min.js');
  app.import('bower_components/mousetrap/plugins/global-bind/mousetrap-global-bind.min.js');
  app.import('vendor/shims/mousetrap.js', {
    exports: {
      'mousetrap': ['default']
    }
  });

  app.import('bower_components/pubsub-js-client/dist/pubsub.js', {
    exports: {
      'pubsub-js-client/PubsubDriver': ['default']
    }
  });

  app.import('bower_components/flexslider/jquery.flexslider.js');

  app.import('bower_components/algoliasearch/dist/algoliasearch.js');

  app.import('vendor/punycode.min.js');

  app.import('vendor/shims/moment.js', {
    exports: {
      'moment': ['default']
    }
  });

  app.import('bower_components/pikaday/pikaday.js');

  app.import('bower_components/moment-timezone/moment-timezone.js');
  app.import('vendor/shims/moment-timezone.js', {
    exports: {
      'moment-timezone': ['default']
    }
  });

  app.import('vendor/shims/es6-map-shim.js');
  app.import('bower_components/promise-throttle/dist/promise-throttle.js');

  return app;
};
var _allFeatureFilesToStripFromApp = function(app, tree) {
  var buildNames = Object.keys(featuresBuilds);
  var featureGroup = buildNames.map(function(feature){
    return featuresBuilds[feature].map(function(file){
      return 'web-client/' + file;
    });
  });

  return [].concat.apply([], featureGroup);
}

var _buildFeatureFiles = function (app, tree, originalConcatFiles) {
  var buildNames = Object.keys(featuresBuilds);
  var featuresGroup = buildNames.map(function(feature){

    var featureFiles = featuresBuilds[feature].map(function(file){
      return 'web-client/' + file;
    });

    // Create a tree of modules that have been removed from the main build
    var featureTree = funnel(tree, {
      include: featureFiles
    });

    // Create a files to be added to the top of the feature file.
    // Push the name of the feature into the window global `features`
    var headerFile = 'window.features = window.features || [];  window.features.push("' + feature + '");';

    // Concat the modules that have been stripped from the main build into the features file name. ie: `fuel.js`
    return originalConcatFiles.call(app, featureTree, {
      annotation: 'Concat: ' + feature + ' files',
      outputFile: feature + '.js',
      header: headerFile,
      inputFiles: [
        '**/*.js'
      ],
      allowNone: true
    });
  });

  return mergeTrees(featuresGroup.filter(Boolean));
}

exports.buildTestApp = function (defaults, _trees, includeFiles) {
  includeFiles = includeFiles || [];
  var trees = _trees || {};

  var testApp = _buildApp(defaults, trees);
  testApp.hinting = true;
  var testAppTree = testApp.toTree();

  testApp.import('bower_components/flexslider/jquery.flexslider.js');

  return mergeTrees([
    testAppTree,
    require('./benchmark/Brocfile'),
    require('./global/Brocfile'),
    funnel(testAppTree, {
      srcDir: '/',
      files: includeFiles,
      destDir: '/'
    }),
    funnel('node_modules/twitch-styles', {
      srcDir: 'static/css',
      destDir: 'styles'
    })
  ], { overwrite: true });
};

exports.buildApp = function (defaults, options) {
  options.include = options.include || [];

  var filename = '/' + options.filename,
      app = _buildApp(defaults, options.trees),
      appTree = app.toTree();

  app = app.concatFiles(appTree, {
    wrapInEval: false,
    outputFile: filename,
    inputFiles: [
      'assets/vendor.js',
      'assets/web-client.js'
    ]
  });

  if (options.onlyFile) {
    options.include.push(filename);
    return funnel(app, { files: options.include });
  }

  return mergeTrees([
    app,
    funnel(appTree, {
      include: options.include,
      srcDir: '/',
      destDir: '/'
    })
  ], {overwrite: true});
};

exports.fingerprintApp = function(tree) {
  tree = new AssetRev(tree, {
    extensions: ['js'],
    replaceExtensions: ['html'],
    prepend: '{{.WebClientHostport}}/',
    exclude: [
      'translations/**/*.js'
    ]
  });

  // preserve old files... :/
  withoutFingerPrint = funnel(tree, {
    getDestinationPath(relativePath) {
      let basename = path.basename(relativePath, '.js');
      let filename = basename.substr(0, basename.lastIndexOf('-')) + '.js';
      let dirname = path.dirname(relativePath);
      return path.join(dirname, filename);
    },

    include: ['**/*-*.js'],
    exclude: [
      'translations/**/*.js'
    ]
  });

  return mergeTrees([withoutFingerPrint, tree]);
}
