var tests = require("../test/fbtest.js");
var stringify = require("./stringify");
var esprima = require("../esprima.js");
var fs = require("fs");
var numTests = 0;

var out = "/*\n"
out += "* WARNING: This file is autogenerated by tools/generate-fbtest.js\n";
out += "* Do NOT modify this file directly! Instead, add your tests to\n";
out += "* tests/fbtest.js and run tools/generate-fbtest.js\n";
out += "*/\n\n";

for (section in tests) {
  if (tests.hasOwnProperty(section)) {
    numTests += tests[section].length;
  }
}

out += "var numTests = " + numTests + "\n";

var options = {
    comment: false,
    range: true,
    loc: true,
    sourceType: 'module',
    tokens: false,
    raw: true,
    tolerant: false
};

function escape_content(content) {
  return content
    .replace(/[\\]/g, '\\\\')
    .replace(/[\b]/g, '\\b')
    .replace(/[\f]/g, '\\f')
    .replace(/[\n]/g, '\\n')
    .replace(/[\r]/g, '\\r')
    .replace(/[\t]/g, '\\t')
    .replace(/[']/g, "\\'");
}

function logUnexpectedResult(section, test, expectedError) {
  var expected = expectedError ? 'error' : 'AST';
  var result = expectedError ? 'AST' : 'error';
  console.error(
    '[' + section + '] Expected "' + test + '" ' +
    'to result in an ' + expected + ' but got an ' + result + ' instead.'
  );
}

out += "var testFixture;\n\n";
out += "var fbTestFixture = {\n";
var ast, result;
for (section in tests) {
  out += "    '"+section+"': {\n";
  var expectError = /^Invalid/.test(section);
  for (test in tests[section]) {
    test = tests[section][test];
    out += "        '"+escape_content(test)+"': {\n";
    var gotError = false;
    try {
      ast = esprima.parse(test, options);
      result = stringify(ast.body[0]);
      result = result
          .substr(2, result.length-4)
          .split("\n")
          .map(function(x) { return "        "+x; });
      out += result.join("\n");
    } catch (e) {
      gotError = true;

      out += "            index: "+e.index+",\n";
      out += "            lineNumber: "+e.lineNumber+",\n";
      out += "            column: "+e.column+",\n";
      out += "            message: 'Error: "+e.message+"',\n";
      out += "            description: '"+e.description+"'\n";
    }
    out += "\n";
    out += "        },\n";

    if (expectError !== gotError) {
      logUnexpectedResult(section, escape_content(test), expectError);
    }
  }
  out += "    },\n";
}

out += "};\n\n\
\/\/ Merge fbTestFixture in to testFixture\n\
\n\
(function () {\n\
\n\
    'use strict';\n\
\n\
    var i, j, fixtures;\n\
\n\
    for (i in fbTestFixture) {\n\
        if (fbTestFixture.hasOwnProperty(i)) {\n\
            for (j in fbTestFixture[i]) {\n\
              numTests--;\n\
            }\n\
            fixtures = fbTestFixture[i];\n\
            if (i !== 'Syntax' && testFixture.hasOwnProperty(i)) {\n\
                throw new Error('FB test should not replace existing test for ' + i);\n\
            }\n\
            testFixture[i] = fixtures;\n\
            testFixtureOptions[i] = {sourceType: 'module'};\n\
\n\
            if (/( \\(module and script\\)$)/.test(i)) {\n\
              testFixture[i + ' (non-module)'] = fixtures;\n\
            }\n\
        }\n\
    }\n\
\n\
    if (numTests !== 0) {\n\
      console.log(numTests);\n\
      throw new Error(\n\
        'Our terrible checksum check failed. '+\n\
        'Did you modify fbtest.rec.js directly? '+\n\
        'Please add your test to fbtest.js instead.'\n\
      );\n\
    }\n\
\n\
}());\n"

fs.writeFileSync(__dirname+'/../test/fbtest.rec.js', out);
console.log("Recorded fbtest.js output into fbtest.rec.js");
