// Copyright 2007-2010 Baptiste Lepilleur
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE

/* This executable is used for testing parser/writer using real JSON files.
 */

#include <json/json.h>
#include <algorithm> // sort
#include <stdio.h>

#if defined(_MSC_VER) && _MSC_VER >= 1310
#pragma warning(disable : 4996) // disable fopen deprecation warning
#endif

static std::string normalizeFloatingPointStr(double value) {
  char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
  sprintf_s(buffer, sizeof(buffer), "%.16g", value);
#else
  snprintf(buffer, sizeof(buffer), "%.16g", value);
#endif
  buffer[sizeof(buffer) - 1] = 0;
  std::string s(buffer);
  std::string::size_type index = s.find_last_of("eE");
  if (index != std::string::npos) {
    std::string::size_type hasSign =
        (s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
    std::string::size_type exponentStartIndex = index + 1 + hasSign;
    std::string normalized = s.substr(0, exponentStartIndex);
    std::string::size_type indexDigit =
        s.find_first_not_of('0', exponentStartIndex);
    std::string exponent = "0";
    if (indexDigit !=
        std::string::npos) // There is an exponent different from 0
    {
      exponent = s.substr(indexDigit);
    }
    return normalized + exponent;
  }
  return s;
}

static std::string readInputTestFile(const char* path) {
  FILE* file = fopen(path, "rb");
  if (!file)
    return std::string("");
  fseek(file, 0, SEEK_END);
  long size = ftell(file);
  fseek(file, 0, SEEK_SET);
  std::string text;
  char* buffer = new char[size + 1];
  buffer[size] = 0;
  if (fread(buffer, 1, size, file) == (unsigned long)size)
    text = buffer;
  fclose(file);
  delete[] buffer;
  return text;
}

static void
printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
  if (value.hasComment(Json::commentBefore)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
  }
  switch (value.type()) {
  case Json::nullValue:
    fprintf(fout, "%s=null\n", path.c_str());
    break;
  case Json::intValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestInt()).c_str());
    break;
  case Json::uintValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            Json::valueToString(value.asLargestUInt()).c_str());
    break;
  case Json::realValue:
    fprintf(fout,
            "%s=%s\n",
            path.c_str(),
            normalizeFloatingPointStr(value.asDouble()).c_str());
    break;
  case Json::stringValue:
    fprintf(fout, "%s=\"%s\"\n", path.c_str(), value.asString().c_str());
    break;
  case Json::booleanValue:
    fprintf(fout, "%s=%s\n", path.c_str(), value.asBool() ? "true" : "false");
    break;
  case Json::arrayValue: {
    fprintf(fout, "%s=[]\n", path.c_str());
    int size = value.size();
    for (int index = 0; index < size; ++index) {
      static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
      sprintf_s(buffer, sizeof(buffer), "[%d]", index);
#else
      snprintf(buffer, sizeof(buffer), "[%d]", index);
#endif
      printValueTree(fout, value[index], path + buffer);
    }
  } break;
  case Json::objectValue: {
    fprintf(fout, "%s={}\n", path.c_str());
    Json::Value::Members members(value.getMemberNames());
    std::sort(members.begin(), members.end());
    std::string suffix = *(path.end() - 1) == '.' ? "" : ".";
    for (Json::Value::Members::iterator it = members.begin();
         it != members.end();
         ++it) {
      const std::string& name = *it;
      printValueTree(fout, value[name], path + suffix + name);
    }
  } break;
  default:
    break;
  }

  if (value.hasComment(Json::commentAfter)) {
    fprintf(fout, "%s\n", value.getComment(Json::commentAfter).c_str());
  }
}

static int parseAndSaveValueTree(const std::string& input,
                                 const std::string& actual,
                                 const std::string& kind,
                                 Json::Value& root,
                                 const Json::Features& features,
                                 bool parseOnly) {
  Json::Reader reader(features);
  bool parsingSuccessful = reader.parse(input, root);
  if (!parsingSuccessful) {
    printf("Failed to parse %s file: \n%s\n",
           kind.c_str(),
           reader.getFormattedErrorMessages().c_str());
    return 1;
  }

  if (!parseOnly) {
    FILE* factual = fopen(actual.c_str(), "wt");
    if (!factual) {
      printf("Failed to create %s actual file.\n", kind.c_str());
      return 2;
    }
    printValueTree(factual, root);
    fclose(factual);
  }
  return 0;
}

static int rewriteValueTree(const std::string& rewritePath,
                            const Json::Value& root,
                            std::string& rewrite) {
  // Json::FastWriter writer;
  // writer.enableYAMLCompatibility();
  Json::StyledWriter writer;
  rewrite = writer.write(root);
  FILE* fout = fopen(rewritePath.c_str(), "wt");
  if (!fout) {
    printf("Failed to create rewrite file: %s\n", rewritePath.c_str());
    return 2;
  }
  fprintf(fout, "%s\n", rewrite.c_str());
  fclose(fout);
  return 0;
}

static std::string removeSuffix(const std::string& path,
                                const std::string& extension) {
  if (extension.length() >= path.length())
    return std::string("");
  std::string suffix = path.substr(path.length() - extension.length());
  if (suffix != extension)
    return std::string("");
  return path.substr(0, path.length() - extension.length());
}

static void printConfig() {
// Print the configuration used to compile JsonCpp
#if defined(JSON_NO_INT64)
  printf("JSON_NO_INT64=1\n");
#else
  printf("JSON_NO_INT64=0\n");
#endif
}

static int printUsage(const char* argv[]) {
  printf("Usage: %s [--strict] input-json-file", argv[0]);
  return 3;
}

int parseCommandLine(int argc,
                     const char* argv[],
                     Json::Features& features,
                     std::string& path,
                     bool& parseOnly) {
  parseOnly = false;
  if (argc < 2) {
    return printUsage(argv);
  }

  int index = 1;
  if (std::string(argv[1]) == "--json-checker") {
    features = Json::Features::strictMode();
    parseOnly = true;
    ++index;
  }

  if (std::string(argv[1]) == "--json-config") {
    printConfig();
    return 3;
  }

  if (index == argc || index + 1 < argc) {
    return printUsage(argv);
  }

  path = argv[index];
  return 0;
}

int main(int argc, const char* argv[]) {
  std::string path;
  Json::Features features;
  bool parseOnly;
  int exitCode = parseCommandLine(argc, argv, features, path, parseOnly);
  if (exitCode != 0) {
    return exitCode;
  }

  try {
    std::string input = readInputTestFile(path.c_str());
    if (input.empty()) {
      printf("Failed to read input or empty input: %s\n", path.c_str());
      return 3;
    }

    std::string basePath = removeSuffix(argv[1], ".json");
    if (!parseOnly && basePath.empty()) {
      printf("Bad input path. Path does not end with '.expected':\n%s\n",
             path.c_str());
      return 3;
    }

    std::string actualPath = basePath + ".actual";
    std::string rewritePath = basePath + ".rewrite";
    std::string rewriteActualPath = basePath + ".actual-rewrite";

    Json::Value root;
    exitCode = parseAndSaveValueTree(
        input, actualPath, "input", root, features, parseOnly);
    if (exitCode == 0 && !parseOnly) {
      std::string rewrite;
      exitCode = rewriteValueTree(rewritePath, root, rewrite);
      if (exitCode == 0) {
        Json::Value rewriteRoot;
        exitCode = parseAndSaveValueTree(rewrite,
                                         rewriteActualPath,
                                         "rewrite",
                                         rewriteRoot,
                                         features,
                                         parseOnly);
      }
    }
  }
  catch (const std::exception& e) {
    printf("Unhandled exception:\n%s\n", e.what());
    exitCode = 1;
  }

  return exitCode;
}
