/*
 * 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 "parser/wat-parser.h"
#include "support/debug.h"
#include "support/path.h"
#include "wasm-binary.h"

namespace wasm {

#define DEBUG_TYPE "writer"

static void readTextData(std::optional<std::string> filename,
                         std::string_view input,
                         Module& wasm,
                         IRProfile profile) {
  if (auto parsed = WATParser::parseModule(wasm, input, filename);
      auto err = parsed.getErr()) {
    Fatal() << err->msg;
  }
}

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(filename, input, wasm, profile);
}

void ModuleReader::readBinaryData(const std::vector<char>& input,
                                  Module& wasm,
                                  std::string sourceMapFilename) {
  std::vector<char> sourceMapBuffer;
  if (sourceMapFilename.size()) {
    sourceMapBuffer =
      read_file<std::vector<char>>(sourceMapFilename, Flags::Text);
  }
  // Assume that the wasm has had its initial features applied, and use those
  // while parsing.
  WasmBinaryReader parser(wasm, wasm.features, input, sourceMapBuffer);
  parser.setDebugInfo(debugInfo);
  parser.setDWARF(DWARF);
  parser.setSkipFunctionBodies(skipFunctionBodies);
  parser.read();
  if (wasm.hasFeaturesSection) {
    featuresSectionFeatures = parser.getFeaturesSectionFeatures();
  }
}

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(wasm::Path::to_path(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);
  }
}

void ModuleReader::readData(const std::vector<char>& input,
                            Module& wasm,
                            std::string sourceMapFilename) {
  if (input.size() >= 4 && input[0] == '\0' && input[1] == 'a' &&
      input[2] == 's' && input[3] == 'm') {
    readBinaryData(input, wasm, sourceMapFilename);
  } else {
    readTextData(std::nullopt,
                 std::string_view(input.data(), input.size()),
                 wasm,
                 profile);
  }
}

void ModuleReader::readStdin(Module& wasm, std::string sourceMapFilename) {
  std::vector<char> input = read_stdin();
  readData(input, wasm, sourceMapFilename);
}

#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, BufferWithRandomAccess& buffer) {
  WasmBinaryWriter writer(&wasm, buffer, options);
  // 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 = std::make_unique<std::ofstream>();
    sourceMapStream->open(wasm::Path::to_path(sourceMapFilename));
    if (!sourceMapStream->is_open()) {
      Fatal() << "Failed opening sourcemap output file '" << sourceMapFilename
              << "'";
    }
    writer.setSourceMap(sourceMapStream.get(), sourceMapUrl);
  }
  if (symbolMap.size() > 0) {
    writer.setSymbolMap(symbolMap);
  }
  writer.write();
  if (sourceMapStream) {
    sourceMapStream->close();
  }
}

void ModuleWriter::writeBinary(Module& wasm, Output& output) {
  BufferWithRandomAccess buffer;
  writeBinary(wasm, buffer);
  buffer.writeTo(output);
}

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);
  }
}

void ModuleWriter::write(Module& wasm, std::vector<char>& output) {
  if (binary) {
    BufferWithRandomAccess buffer;
    writeBinary(wasm, buffer);
    output.assign(buffer.begin(), buffer.end());
  } else {
    std::ostringstream s;
    s << wasm;
    std::string str = s.str();
    output.assign(str.begin(), str.end());
  }
}

} // namespace wasm
