var _ = require('lodash');
var path = require('canonical-path');
var Q = require('q');
var nunjucks = require('nunjucks');
var log = require('winston');
var writer = require('./utils/doc-writer');
var templateFinderFactory = require('./utils/template-finder');

module.exports = function docRendererFactory(config) {

  if ( !config ) {
    throw new Error('Configuration missing.  Please provide a valid configuration object');
  }
  if ( !config.basePath ) {
    throw new Error('Invalid configuration: You must provide a basePath in the configuration object');
  }
  if ( !config.rendering || !config.rendering.templateFolder || !config.rendering.outputFolder ) {
    throw new Error('Invalid configuration: You must provide a valid config.rendering object');
  }

  // Resolve the paths to the templates and output folder
  config.rendering.templateFolder = path.resolve(config.basePath, config.rendering.templateFolder);
  config.rendering.outputFolder = path.resolve(config.basePath, config.rendering.outputFolder);

  var templateFinder = templateFinderFactory(config);

  // Lets use {$ $} for nunjucks interpolation rather than {{ }}, which conflicts with AngularJS
  var env = nunjucks.configure(config.rendering.templateFolder, {
    tags: {
      variableStart: '{$',
      variableEnd: '$}'
    }
  });


  // Configure nunjucks with the custom filters
  _.forEach(config.rendering.filters, function(filter) {
    env.addFilter(filter.name, filter.process);
  });


  // Configure nunjucks with the custom tags
  _.forEach(config.rendering.tags, function(tag) {
    env.addExtension(tag.tags[0], tag);
  });

  // Extract any extra helper functions/data from the config
  var helpers = _.defaults({}, config.helpers);

  /**
   * Render the set of documents to the output folder and extra data, using the templates found in the given folder
   * @param  {object} doc          The document to render
   * @param  {object} extraData        Extra data to make available to the rendering
   * @returns {promise}            A promise to each of the output paths, resolved when all the docs have
   *                               been rendered and output
   */
  return function render(docs, extraData) {
    var fileWritePromises = [];
    
    _.forEach(docs, function(doc) {
      var data, res, outputFile, err;
      try {
        data = _.defaults({}, { doc: doc, docs: docs }, extraData, helpers);
        outputFile = path.resolve(config.rendering.outputFolder, doc.outputPath);
        var templateFile = templateFinder(data.doc);
        res = nunjucks.render(templateFile, data);

        log.debug('outputFile', doc.outputPath, outputFile);

        fileWritePromises.push(writer.writeFile(outputFile, res).then(function() {
          log.debug('Rendered doc', outputFile);
          return outputFile;
        }));
      } catch(ex) {
        throw new Error('Failed to render doc "' + doc.id + '"from file "' + doc.file + '" line ' + doc.startingLine + '\n Error Message follows:\n' + ex.stack);
      }
      
    });

    return Q.all(fileWritePromises);
  };

};
@@ -2317,16 +2317,152 @@
 e, err;%0A
+      if ( !doc.outputPath ) %7B%0A        throw new Error('Invalid document %22' + doc.id + '%22 - this document has no outputPath.');%0A      %7D%0A
       tr
@@ -3047,16 +3047,17 @@
 .id + '%22
+ 
 from fil

add better error message for no outputPath