/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Emit a JavaScript wrapper to run a wasm module with some test
// values, useful for fuzzing.
//

#include "wasm-type.h"
#include "wasm.h"
#include <string>

namespace wasm {

inline std::string generateJSWrapper(Module& wasm) {
  std::string ret;
  ret += "if (typeof console === 'undefined') {\n"
         "  console = { log: print };\n"
         "}\n"
         "var tempRet0;\n"
         "var binary;\n"
         "if (typeof process === 'object' && typeof require === 'function' /* "
         "node.js detection */) {\n"
         "  var args = process.argv.slice(2);\n"
         "  binary = require('fs').readFileSync(args[0]);\n"
         "  if (!binary.buffer) binary = new Uint8Array(binary);\n"
         "} else {\n"
         "  var args;\n"
         "  if (typeof scriptArgs != 'undefined') {\n"
         "    args = scriptArgs;\n"
         "  } else if (typeof arguments != 'undefined') {\n"
         "    args = arguments;\n"
         "  }\n"
         "  if (typeof readbuffer === 'function') {\n"
         "    binary = new Uint8Array(readbuffer(args[0]));\n"
         "  } else {\n"
         "    binary = read(args[0], 'binary');\n"
         "  }\n"
         "}\n"
         "function literal(x, type) {\n"
         "  var ret = '';\n"
         "  switch (type) {\n"
         "    case 'i32': ret += (x | 0); break;\n"
         "    case 'f32':\n"
         "    case 'f64': {\n"
         "      if (x == 0 && (1 / x) < 0) ret += '-';\n"
         "      ret += Number(x).toString();\n"
         "      break;\n"
         "    }\n"
         "    // For anything else, just print the type.\n"
         "    default: ret += type; break;\n"
         "  }\n"
         "  return ret;\n"
         "}\n"
         "var instance = new WebAssembly.Instance(new "
         "WebAssembly.Module(binary), {\n"
         "  'fuzzing-support': {\n"
         "    'log-i32': function(x)    { "
         "console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') "
         "+ ']') },\n"
         "    'log-i64': function(x, y) { "
         "console.log('[LoggingExternalInterface logging ' + literal(x, 'i32') "
         "+ ' ' + literal(y, 'i32') + ']') },\n" // legalization: two i32s
         "    'log-f32': function(x)    { "
         "console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') "
         "+ ']') },\n" // legalization: an f64
         "    'log-f64': function(x)    { "
         "console.log('[LoggingExternalInterface logging ' + literal(x, 'f64') "
         "+ ']') },\n"
         "  },\n"
         "  'env': {\n"
         "    'setTempRet0': function(x) { tempRet0 = x },\n"
         "    'getTempRet0': function() { return tempRet0 },\n"
         "  },\n"
         "});\n";
  for (auto& exp : wasm.exports) {
    if (exp->kind != ExternalKind::Function) {
      continue; // something exported other than a function
    }
    auto* func = wasm.getFunction(exp->value);
    ret += "if (instance.exports.hangLimitInitializer) "
           "instance.exports.hangLimitInitializer();\n";
    ret += "try {\n";
    ret += std::string("  console.log('[fuzz-exec] calling ") + exp->name.str +
           "');\n";
    if (func->getResults() != Type::none) {
      ret += std::string("  console.log('[fuzz-exec] note result: ") +
             exp->name.str + " => ' + literal(";
    } else {
      ret += "  ";
    }
    ret += std::string("instance.exports.") + exp->name.str + "(";
    bool first = true;
    for (auto param : func->getParams()) {
      // zeros in arguments TODO more?
      if (first) {
        first = false;
      } else {
        ret += ", ";
      }
      if (param.isRef()) {
        ret += "null";
      } else {
        ret += "0";
        if (param == Type::i64) {
          ret += ", 0";
        }
      }
    }
    ret += ")";
    if (func->getResults() != Type::none) {
      ret += ", '" + func->getResults().toString() + "'))";
      // TODO: getTempRet
    }
    ret += ";\n";
    ret += "} catch (e) {\n";
    ret += "  console.log('exception!' /* + e */);\n";
    ret += "}\n";
  }
  return ret;
}

} // namespace wasm
