'use strict';

var grunt = require('../grunt');

// The module to be exported.
var template = module.exports = {};

// External libs.
template.date = require('dateformat');

// Format today's date.
template.today = function(format) {
  return template.date(new Date(), format);
};

// Template delimiters.
var allDelimiters = {};

// Initialize template delimiters.
template.addDelimiters = function(name, opener, closer) {
  var delimiters = allDelimiters[name] = {};
  // Used by grunt.
  delimiters.opener = opener;
  delimiters.closer = closer;
  // Generate RegExp patterns dynamically.
  var a = delimiters.opener.replace(/(.)/g, '\\$1');
  var b = '([\\s\\S]+?)' + delimiters.closer.replace(/(.)/g, '\\$1');
  // Used by Lo-Dash.
  delimiters.lodash = {
    evaluate: new RegExp(a + b, 'g'),
    interpolate: new RegExp(a + '=' + b, 'g'),
    escape: new RegExp(a + '-' + b, 'g')
  };
};

// The underscore default template syntax should be a pretty sane default for
// the config system.
template.addDelimiters('config', '<%', '%>');

// Set Lo-Dash template delimiters.
template.setDelimiters = function(name) {
  // Get the appropriate delimiters.
  var delimiters = allDelimiters[name in allDelimiters ? name : 'config'];
  // Tell Lo-Dash which delimiters to use.
  grunt.util._.extend(grunt.util._.templateSettings, delimiters.lodash);
  // Return the delimiters.
  return delimiters;
};

// Process template + data with Lo-Dash.
template.process = function(tmpl, options) {
  if (!options) { options = {}; }
  // Set delimiters, and get a opening match character.
  var delimiters = template.setDelimiters(options.delimiters);
  // Clone data, initializing to config data or empty object if omitted.
  var data = Object.create(options.data || grunt.config.data || {});
  // Expose grunt so that grunt utilities can be accessed, but only if it
  // doesn't conflict with an existing .grunt property.
  if (!('grunt' in data)) { data.grunt = grunt; }
  // Keep track of last change.
  var last = tmpl;
  try {
    // As long as tmpl contains template tags, render it and get the result,
    // otherwise just use the template string.
    while (tmpl.indexOf(delimiters.opener) >= 0) {
      tmpl = grunt.util._.template(tmpl, options)(data);
      // Abort if template didn't change - nothing left to process!
      if (tmpl === last) { break; }
      last = tmpl;
    }
  } catch (e) {
    // In upgrading to Lo-Dash (or Underscore.js 1.3.3), \n and \r in template
    // tags now causes an exception to be thrown. Warn the user why this is
    // happening. https://github.com/documentcloud/underscore/issues/553
    if (String(e) === 'SyntaxError: Unexpected token ILLEGAL' && /\n|\r/.test(tmpl)) {
      grunt.log.errorlns('A special character was detected in this template. ' +
        'Inside template tags, the \\n and \\r special characters must be ' +
        'escaped as \\\\n and \\\\r. (grunt 0.4.0+)');
    }
    // Slightly better error message.
    e.message = 'An error occurred while processing a template (' + e.message + ').';
    grunt.warn(e, grunt.fail.code.TEMPLATE_ERROR);
  }
  // Normalize linefeeds and return.
  return grunt.util.normalizelf(tmpl);
};
