// Copyright 2021 The Tint Authors.
//
// 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 <fstream>
#include <iostream>

#include "fuzzers/tint_spirv_tools_fuzzer/util.h"

namespace tint {
namespace fuzzers {
namespace spvtools_fuzzer {
namespace util {
namespace {

bool WriteBinary(const std::string& path, const uint8_t* data, size_t size) {
  std::ofstream spv(path, std::ios::binary);
  return spv && spv.write(reinterpret_cast<const char*>(data),
                          static_cast<std::streamsize>(size));
}

void LogError(uint32_t index,
              const std::string& type,
              const std::string& message,
              const std::string* path,
              const uint8_t* data,
              size_t size,
              const std::string* wgsl) {
  std::cout << index << " | " << type << ": " << message << std::endl;

  if (path) {
    auto prefix = *path + std::to_string(index);
    std::ofstream(prefix + ".log") << message << std::endl;

    WriteBinary(prefix + ".spv", data, size);

    if (wgsl) {
      std::ofstream(prefix + ".wgsl") << *wgsl << std::endl;
    }
  }
}

}  // namespace

spvtools::MessageConsumer GetBufferMessageConsumer(std::stringstream* buffer) {
  return [buffer](spv_message_level_t level, const char*,
                  const spv_position_t& position, const char* message) {
    std::string status;
    switch (level) {
      case SPV_MSG_FATAL:
      case SPV_MSG_INTERNAL_ERROR:
      case SPV_MSG_ERROR:
        status = "ERROR";
        break;
      case SPV_MSG_WARNING:
      case SPV_MSG_INFO:
      case SPV_MSG_DEBUG:
        status = "INFO";
        break;
    }
    *buffer << status << " " << position.line << ":" << position.column << ":"
            << position.index << ": " << message << std::endl;
  };
}

void LogMutatorError(const Mutator& mutator, const std::string& error_dir) {
  static uint32_t mutator_count = 0;
  auto error_path = error_dir.empty() ? error_dir : error_dir + "/mutator/";
  mutator.LogErrors(error_dir.empty() ? nullptr : &error_path, mutator_count++);
}

void LogWgslError(const std::string& message,
                  const uint8_t* data,
                  size_t size,
                  const std::string& wgsl,
                  OutputFormat output_format,
                  const std::string& error_dir) {
  static uint32_t wgsl_count = 0;
  std::string error_type;
  switch (output_format) {
    case OutputFormat::kSpv:
      error_type = "WGSL -> SPV";
      break;
    case OutputFormat::kMSL:
      error_type = "WGSL -> MSL";
      break;
    case OutputFormat::kHLSL:
      error_type = "WGSL -> HLSL";
      break;
    case OutputFormat::kWGSL:
      error_type = "WGSL -> WGSL";
      break;
    default:
      assert(false && "All output formats should've been handled");
      break;
  }
  auto error_path = error_dir.empty() ? error_dir : error_dir + "/wgsl/";
  LogError(wgsl_count++, error_type, message,
           error_dir.empty() ? nullptr : &error_path, data, size, &wgsl);
}

void LogSpvError(const std::string& message,
                 const uint8_t* data,
                 size_t size,
                 const std::string& error_dir) {
  static uint32_t spv_count = 0;
  auto error_path = error_dir.empty() ? error_dir : error_dir + "/spv/";
  LogError(spv_count++, "SPV -> WGSL", message,
           error_dir.empty() ? nullptr : &error_path, data, size, nullptr);
}

bool ReadBinary(const std::string& path, std::vector<uint32_t>* out) {
  if (!out) {
    return false;
  }

  std::ifstream file(path, std::ios::binary | std::ios::ate);
  if (!file) {
    return false;
  }

  size_t size = static_cast<size_t>(file.tellg());
  if (!file) {
    return false;
  }

  file.seekg(0);
  if (!file) {
    return false;
  }

  std::vector<char> binary(size);
  if (!file.read(binary.data(), size)) {
    return false;
  }

  out->resize(binary.size() / sizeof(uint32_t));
  std::memcpy(out->data(), binary.data(), binary.size());
  return true;
}

bool WriteBinary(const std::string& path, const std::vector<uint32_t>& binary) {
  return WriteBinary(path, reinterpret_cast<const uint8_t*>(binary.data()),
                     binary.size() * sizeof(uint32_t));
}

}  // namespace util
}  // namespace spvtools_fuzzer
}  // namespace fuzzers
}  // namespace tint
