/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */

#include "cmJSONState.h"

#include <sstream>

#include <cm/memory>

#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>

#include "cmsys/FStream.hxx"

#include "cmStringAlgorithms.h"

cmJSONState::cmJSONState(const std::string& filename, Json::Value* root)
{
  cmsys::ifstream fin(filename.c_str(), std::ios::in | std::ios::binary);
  if (!fin) {
    this->AddError(cmStrCat("File not found: ", filename));
    return;
  }
  // If there's a BOM, toss it.
  cmsys::FStream::ReadBOM(fin);

  // Save the entire document.
  std::streampos finBegin = fin.tellg();
  this->doc = std::string(std::istreambuf_iterator<char>(fin),
                          std::istreambuf_iterator<char>());
  if (this->doc.empty()) {
    this->AddError("A JSON document cannot be empty");
    return;
  }
  fin.seekg(finBegin);

  // Parse the document.
  Json::CharReaderBuilder builder;
  Json::CharReaderBuilder::strictMode(&builder.settings_);
  std::string errMsg;
  if (!Json::parseFromStream(builder, fin, root, &errMsg)) {
    errMsg = cmStrCat("JSON Parse Error: ", filename, ":\n", errMsg);
    this->AddError(errMsg);
  }
}

void cmJSONState::AddError(std::string const& errMsg)
{
  this->errors.push_back(Error(errMsg));
}

void cmJSONState::AddErrorAtValue(std::string const& errMsg,
                                  const Json::Value* value)
{
  if (value && !value->isNull()) {
    this->AddErrorAtOffset(errMsg, value->getOffsetStart());
  } else {
    this->AddError(errMsg);
  }
}

void cmJSONState::AddErrorAtOffset(std::string const& errMsg,
                                   std::ptrdiff_t offset)
{
  if (doc.empty()) {
    this->AddError(errMsg);
  } else {
    Location loc = LocateInDocument(offset);
    this->errors.push_back(Error(loc, errMsg));
  }
}

std::string cmJSONState::GetErrorMessage(bool showContext)
{
  std::string message;
  for (auto const& error : this->errors) {
    message = cmStrCat(message, error.GetErrorMessage(), "\n");
    if (showContext) {
      Location loc = error.GetLocation();
      if (loc.column > 0) {
        message = cmStrCat(message, GetJsonContext(loc), "\n");
      }
    }
  }
  message = cmStrCat("\n", message);
  message.pop_back();
  return message;
}

std::string cmJSONState::key()
{
  if (!this->parseStack.empty()) {
    return this->parseStack.back().first;
  }
  return "";
}

std::string cmJSONState::key_after(std::string const& k)
{
  for (auto it = this->parseStack.begin(); it != this->parseStack.end();
       ++it) {
    if (it->first == k && (++it) != this->parseStack.end()) {
      return it->first;
    }
  }
  return "";
}

const Json::Value* cmJSONState::value_after(std::string const& k)
{
  for (auto it = this->parseStack.begin(); it != this->parseStack.end();
       ++it) {
    if (it->first == k && (++it) != this->parseStack.end()) {
      return it->second;
    }
  }
  return nullptr;
}

void cmJSONState::push_stack(std::string const& k, const Json::Value* value)
{
  this->parseStack.push_back(JsonPair(k, value));
}

void cmJSONState::pop_stack()
{
  this->parseStack.pop_back();
}

std::string cmJSONState::GetJsonContext(Location loc)
{
  std::string line;
  std::stringstream sstream(doc);
  for (int i = 0; i < loc.line; ++i) {
    std::getline(sstream, line, '\n');
  }
  return cmStrCat(line, '\n', std::string(loc.column - 1, ' '), '^');
}

cmJSONState::Location cmJSONState::LocateInDocument(ptrdiff_t offset)
{
  int line = 1;
  int col = 1;
  const char* beginDoc = doc.data();
  const char* last = beginDoc + offset;
  for (; beginDoc != last; ++beginDoc) {
    switch (*beginDoc) {
      case '\r':
        if (beginDoc + 1 != last && beginDoc[1] == '\n') {
          continue; // consume CRLF as a single token.
        }
        CM_FALLTHROUGH; // CR without a following LF is same as LF
      case '\n':
        col = 1;
        ++line;
        break;
      default:
        ++col;
        break;
    }
  }
  return { line, col };
}
