'use strict';

var fs = require('fs');
var glob = require('glob');
var path = require('path');
var util = require('util');
var rc = require('./rc');
var resolvers = require('./resolvers');
var shared = require('./resolvers.shared');
var defaults = require('./resolvers.cli');

resolvers.use(shared);
resolvers.use(defaults);

function render (force, replacements) {
  if (replacements) {
    resolvers.use(replacements);
  }
  var location = path.resolve(rc.server_routes);
  if (force) {
    delete require.cache[location];
  }
  var routes = require(location);
  return compose(routes);
}

function compose (routes) {
  var buffer = [];
  var templates = glob.sync(path.join(rc.views, '**/*.js'));
  var controllers = glob.sync(path.join(rc.client_controllers, '**/*.js'));
  var first;

  put('"use strict";\n\n');

  first = true;
  put('var templates = {');
  templates.forEach(template);
  put('\n};\n\n');

  first = true;
  put('var controllers = {');
  controllers.forEach(controller);
  put('\n};\n\n');

  first = true;
  put('var routes = {');
  routes.forEach(route);
  put('\n};\n\n');

  put('module.exports = {\n');
  put('  templates: templates,\n');
  put('  controllers: controllers,\n');
  put('  routes: routes\n');
  put('};\n');

  function template (data) {
    var relative = path.relative(rc.views, data);
    var open = first ? '\n' : ',\n';
    put(open);
    put('  "%s": require("%s")', getTemplateName(relative), getTemplatePath(relative));
    first = false;
  }

  function controller (data) {
    var relative = path.relative(rc.client_controllers, data);
    var open = first ? '\n' : ',\n';
    put(open);
    put('  "%s": require("%s")', getTemplateName(relative), getControllerPath(relative));
    first = false;
  }

  function route (data) {
    var open = first ? '\n' : ',\n';
    put(open);
    put('  "%s": {\n', data.route);
    put('    action: "%s"', data.action);

    if (data.ignore) {
      put(',\n');
      put('    ignore: true\n');
    } else {
      put('\n');
    }
    put('  }');
    first = false;
  }

  function put () {
    var value = util.format.apply(util, arguments);
    buffer.push(value);
  }

  return buffer.join('').replace(/"/g, '\'');
}

function getTemplateName (action) {
  return action.replace(/\.js$/, '');
}

function getTemplatePath (action) {
  var location = resolvers.getViewTemplatePath(action);
  return cross(relative(location));
}

function getControllerPath (action) {
  var location = resolvers.getViewControllerPath(action);
  return cross(relative(location));
}

function relative (to) {
  var base = path.dirname(rc.client_wiring);
  return path.relative(base, to);
}

// writing to a file will turn '\\' into '\'
// this function fixes the issue on Windows
function cross (path) {
  return path.replace(/\\/g, '\\\\');
}

module.exports = {
  render: render
};

@@ -1863,16 +1863,42 @@
 route);%0A
+%0A    if (data.action) %7B%0A  
     put(
@@ -1914,16 +1914,20 @@
 on: %22%25s%22
+%25s%5Cn
 ', data.
@@ -1932,18 +1932,48 @@
 a.action
-);
+, data.ignore ? ',' : '');%0A    %7D
 %0A%0A    if
@@ -2004,72 +2004,24 @@
 ut('
-,%5Cn');%0A      put('    ignore: true%5Cn');%0A    %7D else %7B%0A      put('
+    ignore: true
 %5Cn')

include action only if exists