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

#include "support/file.h"
#include "support/debug.h"
#include "support/path.h"
#include "support/utilities.h"

#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <limits>

#define DEBUG_TYPE "file"

std::vector<char> wasm::read_stdin() {
  BYN_TRACE("Loading stdin...\n");
  std::vector<char> input;
  char c;
  while (std::cin.get(c) && !std::cin.eof()) {
    input.push_back(c);
  }
  return input;
}

template<typename T> struct do_read_stdin { T operator()(); };

template<> std::vector<char> do_read_stdin<std::vector<char>>::operator()() {
  return wasm::read_stdin();
}

template<> std::string do_read_stdin<std::string>::operator()() {
  auto vec = wasm::read_stdin();
  return std::string(vec.begin(), vec.end());
}

template<typename T>
T wasm::read_file(const std::string& filename, Flags::BinaryOption binary) {
  if (filename == "-") {
    return do_read_stdin<T>{}();
  }
  BYN_TRACE("Loading '" << filename << "'...\n");
  std::ifstream infile;
  std::ios_base::openmode flags = std::ifstream::in;
  if (binary == Flags::Binary) {
    flags |= std::ifstream::binary;
  }
  infile.open(wasm::Path::to_path(filename), flags);
  if (!infile.is_open()) {
    Fatal() << "Failed opening '" << filename << "'";
  }
  infile.seekg(0, std::ios::end);
  std::streampos insize = infile.tellg();
  if (uint64_t(insize) >= std::numeric_limits<size_t>::max()) {
    // Building a 32-bit executable where size_t == 32 bits, we are not able to
    // create strings larger than 2^32 bytes in length, so must abort here.
    Fatal() << "Failed opening '" << filename
            << "': Input file too large: " << insize
            << " bytes. Try rebuilding in 64-bit mode.";
  }
  // Zero-initialize the string or vector with the expected size.
  T input(size_t(insize), '\0');
  if (size_t(insize) == 0) {
    return input;
  }
  infile.seekg(0);
  infile.read(&input[0], insize);
  if (binary == Flags::Text) {
    size_t chars = size_t(infile.gcount());
    // Truncate size to the number of ASCII characters actually read in text
    // mode (which is generally less than the number of bytes on Windows, if
    // \r\n line endings are present)
    input.resize(chars);
  }
  return input;
}

std::string wasm::read_possible_response_file(const std::string& input) {
  if (input.size() == 0 || input[0] != '@') {
    return input;
  }
  return wasm::read_file<std::string>(input.substr(1), Flags::Text);
}

// Explicit instantiations for the explicit specializations.
template std::string wasm::read_file<>(const std::string&, Flags::BinaryOption);
template std::vector<char> wasm::read_file<>(const std::string&,
                                             Flags::BinaryOption);

wasm::Output::Output(const std::string& filename, Flags::BinaryOption binary)
  : outfile(), out([this, filename, binary]() {
      // Ensure a single return at the very end, to avoid clang-tidy warnings
      // about the types of different returns here.
      std::streambuf* buffer;
      if (filename == "-" || filename.empty()) {
        buffer = std::cout.rdbuf();
      } else {
        BYN_TRACE("Opening '" << filename << "'\n");
        std::ios_base::openmode flags =
          std::ofstream::out | std::ofstream::trunc;
        if (binary == Flags::Binary) {
          flags |= std::ofstream::binary;
        }
        outfile.open(wasm::Path::to_path(filename), flags);
        if (!outfile.is_open()) {
          Fatal() << "Failed opening output file '" << filename
                  << "': " << strerror(errno);
        }
        buffer = outfile.rdbuf();
      }
      return buffer;
    }()) {}

void wasm::copy_file(std::string input, std::string output) {
  std::ifstream src(wasm::Path::to_path(input), std::ios::binary);
  std::ofstream dst(wasm::Path::to_path(output), std::ios::binary);
  dst << src.rdbuf();
}

size_t wasm::file_size(std::string filename) {
  std::ifstream infile(wasm::Path::to_path(filename),
                       std::ifstream::ate | std::ifstream::binary);
  return infile.tellg();
}
