//===-- StructuredData.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cerrno>
#include <cstdlib>
#include <inttypes.h>

using namespace lldb_private;
using namespace llvm;

static StructuredData::ObjectSP ParseJSONValue(json::Value &value);
static StructuredData::ObjectSP ParseJSONObject(json::Object *object);
static StructuredData::ObjectSP ParseJSONArray(json::Array *array);

StructuredData::ObjectSP
StructuredData::ParseJSON(const std::string &json_text) {
  llvm::Expected<json::Value> value = json::parse(json_text);
  if (!value) {
    llvm::consumeError(value.takeError());
    return nullptr;
  }
  return ParseJSONValue(*value);
}

StructuredData::ObjectSP
StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) {
  StructuredData::ObjectSP return_sp;

  auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath());
  if (!buffer_or_error) {
    error.SetErrorStringWithFormatv("could not open input file: {0} - {1}.",
                                    input_spec.GetPath(),
                                    buffer_or_error.getError().message());
    return return_sp;
  }
  llvm::Expected<json::Value> value =
      json::parse(buffer_or_error.get()->getBuffer().str());
  if (value)
    return ParseJSONValue(*value);
  error.SetErrorString(toString(value.takeError()));
  return StructuredData::ObjectSP();
}

static StructuredData::ObjectSP ParseJSONValue(json::Value &value) {
  if (json::Object *O = value.getAsObject())
    return ParseJSONObject(O);

  if (json::Array *A = value.getAsArray())
    return ParseJSONArray(A);

  if (auto s = value.getAsString())
    return std::make_shared<StructuredData::String>(*s);

  if (auto b = value.getAsBoolean())
    return std::make_shared<StructuredData::Boolean>(*b);

  if (auto i = value.getAsInteger())
    return std::make_shared<StructuredData::Integer>(*i);

  if (auto d = value.getAsNumber())
    return std::make_shared<StructuredData::Float>(*d);

  return StructuredData::ObjectSP();
}

static StructuredData::ObjectSP ParseJSONObject(json::Object *object) {
  auto dict_up = std::make_unique<StructuredData::Dictionary>();
  for (auto &KV : *object) {
    StringRef key = KV.first;
    json::Value value = KV.second;
    if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
      dict_up->AddItem(key, value_sp);
  }
  return std::move(dict_up);
}

static StructuredData::ObjectSP ParseJSONArray(json::Array *array) {
  auto array_up = std::make_unique<StructuredData::Array>();
  for (json::Value &value : *array) {
    if (StructuredData::ObjectSP value_sp = ParseJSONValue(value))
      array_up->AddItem(value_sp);
  }
  return std::move(array_up);
}

StructuredData::ObjectSP
StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
  if (this->GetType() == lldb::eStructuredDataTypeDictionary) {
    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
    std::string key = match.first.str();
    ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
    if (value.get()) {
      // Do we have additional words to descend?  If not, return the value
      // we're at right now.
      if (match.second.empty()) {
        return value;
      } else {
        return value->GetObjectForDotSeparatedPath(match.second);
      }
    }
    return ObjectSP();
  }

  if (this->GetType() == lldb::eStructuredDataTypeArray) {
    std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
    if (match.second.empty()) {
      return this->shared_from_this();
    }
    errno = 0;
    uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10);
    if (errno == 0) {
      return this->GetAsArray()->GetItemAtIndex(val);
    }
    return ObjectSP();
  }

  return this->shared_from_this();
}

void StructuredData::Object::DumpToStdout(bool pretty_print) const {
  json::OStream stream(llvm::outs(), pretty_print ? 2 : 0);
  Serialize(stream);
}

void StructuredData::Array::Serialize(json::OStream &s) const {
  s.arrayBegin();
  for (const auto &item_sp : m_items) {
    item_sp->Serialize(s);
  }
  s.arrayEnd();
}

void StructuredData::Integer::Serialize(json::OStream &s) const {
  s.value(static_cast<int64_t>(m_value));
}

void StructuredData::Float::Serialize(json::OStream &s) const {
  s.value(m_value);
}

void StructuredData::Boolean::Serialize(json::OStream &s) const {
  s.value(m_value);
}

void StructuredData::String::Serialize(json::OStream &s) const {
  s.value(m_value);
}

void StructuredData::Dictionary::Serialize(json::OStream &s) const {
  s.objectBegin();
  for (const auto &pair : m_dict) {
    s.attributeBegin(pair.first.GetStringRef());
    pair.second->Serialize(s);
    s.attributeEnd();
  }
  s.objectEnd();
}

void StructuredData::Null::Serialize(json::OStream &s) const {
  s.value(nullptr);
}

void StructuredData::Generic::Serialize(json::OStream &s) const {
  s.value(llvm::formatv("{0:X}", m_object));
}
