/*
 * 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.
 */

//
// Abstracts reading and writing, supporting both text and binary
// depending on the suffix.
//
// When the suffix is unclear, writing defaults to text (this
// allows odd suffixes, which we use in the test suite), while
// reading will check the magic number and default to text if not
// binary.
//

#include "wasm-io.h"
#include "support/debug.h"
#include "wasm-binary.h"
#include "wasm-s-parser.h"
#include "wat-parser.h"


namespace wasm {

bool useNewWATParser = false;

#define DEBUG_TYPE "writer"

static void readTextData(std::string& input, Module& wasm, IRProfile profile) {
  if (useNewWATParser) {
    std::string_view in(input.c_str());
    if (auto parsed = WATParser::parseModule(wasm, in);
        auto err = parsed.getErr()) {
      Fatal() << err->msg;
    }
  } else {
    SExpressionParser parser(const_cast<char*>(input.c_str()));
    Element& root = *parser.root;
    SExpressionWasmBuilder builder(wasm, *root[0], profile);
  }
}

void ModuleReader::readText(std::string filename, Module& wasm) {
  BYN_TRACE("reading text from " << filename << "\n");
  auto input(read_file<std::string>(filename, Flags::Text));
  readTextData(input, wasm, profile);
}

void ModuleReader::readBinaryData(std::vector<char>& input,
                                  Module& wasm,
                                  std::string sourceMapFilename) {
  std::unique_ptr<std::ifstream> sourceMapStream;
  // Assume that the wasm has had its initial features applied, and use those
  // while parsing.
  WasmBinaryBuilder parser(wasm, wasm.features, input);
  parser.setDebugInfo(debugInfo);
  parser.setDWARF(DWARF);
  parser.setSkipFunctionBodies(skipFunctionBodies);
  if (sourceMapFilename.size()) {
    sourceMapStream = make_unique<std::ifstream>();
    sourceMapStream->open(sourceMapFilename);
    parser.setDebugLocations(sourceMapStream.get());
  }
  parser.read();
  if (sourceMapStream) {
    sourceMapStream->close();
  }
}

void ModuleReader::readBinary(std::string filename,
                              Module& wasm,
                              std::string sourceMapFilename) {
  BYN_TRACE("reading binary from " << filename << "\n");
  auto input(read_file<std::vector<char>>(filename, Flags::Binary));
  readBinaryData(input, wasm, sourceMapFilename);
}

bool ModuleReader::isBinaryFile(std::string filename) {
  std::ifstream infile;
  std::ios_base::openmode flags = std::ifstream::in | std::ifstream::binary;
  infile.open(filename, flags);
  char buffer[4] = {1, 2, 3, 4};
  infile.read(buffer, 4);
  infile.close();
  return buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' &&
         buffer[3] == 'm';
}

void ModuleReader::read(std::string filename,
                        Module& wasm,
                        std::string sourceMapFilename) {
  // empty filename or "-" means read from stdin
  if (!filename.size() || filename == "-") {
    readStdin(wasm, sourceMapFilename);
    return;
  }
  if (isBinaryFile(filename)) {
    readBinary(filename, wasm, sourceMapFilename);
  } else {
    // default to text
    if (sourceMapFilename.size()) {
      std::cerr << "Binaryen ModuleReader::read() - source map filename "
                   "provided, but file appears to not be binary\n";
    }
    readText(filename, wasm);
  }
}

// TODO: reading into a vector<char> then copying into a string is unnecessarily
// inefficient. It would be better to read just once into a stringstream.
void ModuleReader::readStdin(Module& wasm, std::string sourceMapFilename) {
  std::vector<char> input = read_stdin();
  if (input.size() >= 4 && input[0] == '\0' && input[1] == 'a' &&
      input[2] == 's' && input[3] == 'm') {
    readBinaryData(input, wasm, sourceMapFilename);
  } else {
    std::ostringstream s;
    s.write(input.data(), input.size());
    s << '\0';
    std::string input_str = s.str();
    readTextData(input_str, wasm, profile);
  }
}

#undef DEBUG_TYPE
#define DEBUG_TYPE "writer"

void ModuleWriter::writeText(Module& wasm, Output& output) {
  output.getStream() << wasm;
}

void ModuleWriter::writeText(Module& wasm, std::string filename) {
  BYN_TRACE("writing text to " << filename << "\n");
  Output output(filename, Flags::Text);
  writeText(wasm, output);
}

void ModuleWriter::writeBinary(Module& wasm, Output& output) {
  BufferWithRandomAccess buffer;
  WasmBinaryWriter writer(&wasm, buffer);
  // if debug info is used, then we want to emit the names section
  writer.setNamesSection(debugInfo);
  if (emitModuleName) {
    writer.setEmitModuleName(true);
  }
  std::unique_ptr<std::ofstream> sourceMapStream;
  if (sourceMapFilename.size()) {
    sourceMapStream = make_unique<std::ofstream>();
    sourceMapStream->open(sourceMapFilename);
    writer.setSourceMap(sourceMapStream.get(), sourceMapUrl);
  }
  if (symbolMap.size() > 0) {
    writer.setSymbolMap(symbolMap);
  }
  writer.write();
  buffer.writeTo(output);
  if (sourceMapStream) {
    sourceMapStream->close();
  }
}

void ModuleWriter::writeBinary(Module& wasm, std::string filename) {
  BYN_TRACE("writing binary to " << filename << "\n");
  Output output(filename, Flags::Binary);
  writeBinary(wasm, output);
}

void ModuleWriter::write(Module& wasm, Output& output) {
  if (binary) {
    writeBinary(wasm, output);
  } else {
    writeText(wasm, output);
  }
}

void ModuleWriter::write(Module& wasm, std::string filename) {
  if (binary && filename.size() > 0) {
    writeBinary(wasm, filename);
  } else {
    writeText(wasm, filename);
  }
}

} // namespace wasm
