//===-- OptionValueProperties.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/Interpreter/OptionValueProperties.h"

#include "lldb/Utility/Flags.h"

#include "lldb/Core/UserSettingsController.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"

using namespace lldb;
using namespace lldb_private;

OptionValueProperties::OptionValueProperties(llvm::StringRef name)
    : m_name(name.str()) {}

void OptionValueProperties::Initialize(
    const PropertyCollectionDefinition &defs) {
  for (const auto &definition : defs.definitions) {
    Property property(definition);
    assert(property.IsValid());
    m_name_to_index.insert({property.GetName(), m_properties.size()});
    property.GetValue()->SetParent(shared_from_this());
    m_properties.push_back(property);
  }
  SetExpectedPath(defs.expected_path.str());
}

void OptionValueProperties::SetExpectedPath(std::string path) {
  assert(m_expected_path.empty() || m_expected_path == path);
  m_expected_path = path;
}

void OptionValueProperties::SetValueChangedCallback(
    size_t property_idx, std::function<void()> callback) {
  Property *property = ProtectedGetPropertyAtIndex(property_idx);
  if (property)
    property->SetValueChangedCallback(std::move(callback));
}

void OptionValueProperties::AppendProperty(llvm::StringRef name,
                                           llvm::StringRef desc, bool is_global,
                                           const OptionValueSP &value_sp) {
  Property property(name, desc, is_global, value_sp);
  m_name_to_index.insert({name, m_properties.size()});
  m_properties.push_back(property);
  value_sp->SetParent(shared_from_this());

#ifndef NDEBUG
  OptionValueProperties *properties = value_sp->GetAsProperties();
  if (properties) {
    assert(value_sp->GetName() == name);
    assert(properties->VerifyPath() &&
           "Mismatch between parents from TableGen and actual parents");
  }
#endif
}

lldb::OptionValueSP
OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
                                      llvm::StringRef key) const {
  auto iter = m_name_to_index.find(key);
  if (iter == m_name_to_index.end())
    return OptionValueSP();
  const size_t idx = iter->second;
  if (idx >= m_properties.size())
    return OptionValueSP();
  return GetPropertyAtIndex(idx, exe_ctx)->GetValue();
}

lldb::OptionValueSP
OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
                                   llvm::StringRef name, Status &error) const {
  lldb::OptionValueSP value_sp;
  if (name.empty())
    return OptionValueSP();

  llvm::StringRef sub_name;
  llvm::StringRef key;
  size_t key_len = name.find_first_of(".[{");
  if (key_len != llvm::StringRef::npos) {
    key = name.take_front(key_len);
    sub_name = name.drop_front(key_len);
  } else
    key = name;

  value_sp = GetValueForKey(exe_ctx, key);
  if (sub_name.empty() || !value_sp)
    return value_sp;

  switch (sub_name[0]) {
  case '.': {
    lldb::OptionValueSP return_val_sp;
    return_val_sp =
        value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), error);
    if (!return_val_sp) {
      if (Properties::IsSettingExperimental(sub_name.drop_front())) {
        const size_t experimental_len =
            Properties::GetExperimentalSettingsName().size();
        if (sub_name[experimental_len + 1] == '.')
          return_val_sp = value_sp->GetSubValue(
              exe_ctx, sub_name.drop_front(experimental_len + 2), error);
        // It isn't an error if an experimental setting is not present.
        if (!return_val_sp)
          error.Clear();
      }
    }
    return return_val_sp;
  }
  case '[':
    // Array or dictionary access for subvalues like: "[12]"       -- access
    // 12th array element "['hello']"  -- dictionary access of key named hello
    return value_sp->GetSubValue(exe_ctx, sub_name, error);

  default:
    value_sp.reset();
    break;
  }
  return value_sp;
}

Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
                                          VarSetOperationType op,
                                          llvm::StringRef name,
                                          llvm::StringRef value) {
  Status error;
  llvm::SmallVector<llvm::StringRef, 8> components;
  name.split(components, '.');
  bool name_contains_experimental = false;
  for (const auto &part : components)
    if (Properties::IsSettingExperimental(part))
      name_contains_experimental = true;

  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, error));
  if (value_sp)
    error = value_sp->SetValueFromString(value, op);
  else {
    // Don't set an error if the path contained .experimental. - those are
    // allowed to be missing and should silently fail.
    if (!name_contains_experimental && error.AsCString() == nullptr) {
      error = Status::FromErrorStringWithFormat("invalid value path '%s'",
                                                name.str().c_str());
    }
  }
  return error;
}

size_t OptionValueProperties::GetPropertyIndex(llvm::StringRef name) const {
  auto iter = m_name_to_index.find(name);
  if (iter == m_name_to_index.end())
    return SIZE_MAX;
  return iter->second;
}

const Property *
OptionValueProperties::GetProperty(llvm::StringRef name,
                                   const ExecutionContext *exe_ctx) const {
  auto iter = m_name_to_index.find(name);
  if (iter == m_name_to_index.end())
    return nullptr;
  return GetPropertyAtIndex(iter->second, exe_ctx);
}

lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
    size_t idx, const ExecutionContext *exe_ctx) const {
  const Property *setting = GetPropertyAtIndex(idx, exe_ctx);
  if (setting)
    return setting->GetValue();
  return OptionValueSP();
}

OptionValuePathMappings *
OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
    size_t idx, const ExecutionContext *exe_ctx) const {
  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
  if (value_sp)
    return value_sp->GetAsPathMappings();
  return nullptr;
}

OptionValueFileSpecList *
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
    size_t idx, const ExecutionContext *exe_ctx) const {
  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
  if (value_sp)
    return value_sp->GetAsFileSpecList();
  return nullptr;
}

bool OptionValueProperties::GetPropertyAtIndexAsArgs(
    size_t idx, Args &args, const ExecutionContext *exe_ctx) const {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (!property)
    return false;

  OptionValue *value = property->GetValue().get();
  if (!value)
    return false;

  const OptionValueArgs *arguments = value->GetAsArgs();
  if (arguments) {
    arguments->GetArgs(args);
    return true;
  }

  const OptionValueArray *array = value->GetAsArray();
  if (array) {
    array->GetArgs(args);
    return true;
  }

  const OptionValueDictionary *dict = value->GetAsDictionary();
  if (dict) {
    dict->GetArgs(args);
    return true;
  }

  return false;
}

bool OptionValueProperties::SetPropertyAtIndexFromArgs(
    size_t idx, const Args &args, const ExecutionContext *exe_ctx) {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (!property)
    return false;

  OptionValue *value = property->GetValue().get();
  if (!value)
    return false;

  OptionValueArgs *arguments = value->GetAsArgs();
  if (arguments)
    return arguments->SetArgs(args, eVarSetOperationAssign).Success();

  OptionValueArray *array = value->GetAsArray();
  if (array)
    return array->SetArgs(args, eVarSetOperationAssign).Success();

  OptionValueDictionary *dict = value->GetAsDictionary();
  if (dict)
    return dict->SetArgs(args, eVarSetOperationAssign).Success();

  return false;
}

OptionValueDictionary *
OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
    size_t idx, const ExecutionContext *exe_ctx) const {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (property)
    return property->GetValue()->GetAsDictionary();
  return nullptr;
}

OptionValueFileSpec *
OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
    size_t idx, const ExecutionContext *exe_ctx) const {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetAsFileSpec();
  }
  return nullptr;
}

OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
    size_t idx, const ExecutionContext *exe_ctx) const {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetAsSInt64();
  }
  return nullptr;
}

OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(
    size_t idx, const ExecutionContext *exe_ctx) const {
  const Property *property = GetPropertyAtIndex(idx, exe_ctx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetAsUInt64();
  }
  return nullptr;
}

OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
    size_t idx, const ExecutionContext *exe_ctx) const {
  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
  if (value_sp)
    return value_sp->GetAsString();
  return nullptr;
}

void OptionValueProperties::Clear() {
  const size_t num_properties = m_properties.size();
  for (size_t i = 0; i < num_properties; ++i)
    m_properties[i].GetValue()->Clear();
}

Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
                                                 VarSetOperationType op) {
  Status error;

  //    Args args(value_cstr);
  //    const size_t argc = args.GetArgumentCount();
  switch (op) {
  case eVarSetOperationClear:
    Clear();
    break;

  case eVarSetOperationReplace:
  case eVarSetOperationAssign:
  case eVarSetOperationRemove:
  case eVarSetOperationInsertBefore:
  case eVarSetOperationInsertAfter:
  case eVarSetOperationAppend:
  case eVarSetOperationInvalid:
    error = OptionValue::SetValueFromString(value, op);
    break;
  }

  return error;
}

void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
                                      Stream &strm, uint32_t dump_mask) {
  const size_t num_properties = m_properties.size();
  for (size_t i = 0; i < num_properties; ++i) {
    const Property *property = GetPropertyAtIndex(i, exe_ctx);
    if (property) {
      OptionValue *option_value = property->GetValue().get();
      assert(option_value);
      const bool transparent_value = option_value->ValueIsTransparent();
      property->Dump(exe_ctx, strm, dump_mask);
      if (!transparent_value)
        strm.EOL();
    }
  }
}

llvm::json::Value
OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) const {
  llvm::json::Object json_properties;
  const size_t num_properties = m_properties.size();
  for (size_t i = 0; i < num_properties; ++i) {
    const Property *property = GetPropertyAtIndex(i, exe_ctx);
    if (property) {
      OptionValue *option_value = property->GetValue().get();
      assert(option_value);
      json_properties.try_emplace(property->GetName(),
                                  option_value->ToJSON(exe_ctx));
    }
  }
  return json_properties;
}

Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
                                                Stream &strm,
                                                llvm::StringRef property_path,
                                                uint32_t dump_mask,
                                                bool is_json) {
  Status error;
  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, property_path, error));
  if (value_sp) {
    if (!value_sp->ValueIsTransparent()) {
      if (dump_mask & eDumpOptionName)
        strm.PutCString(property_path);
      if (dump_mask & ~eDumpOptionName)
        strm.PutChar(' ');
    }
    if (is_json) {
      strm.Printf(
          "%s",
          llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
    } else
      value_sp->DumpValue(exe_ctx, strm, dump_mask);
  }
  return error;
}

OptionValuePropertiesSP
OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
  auto global_props_sp = global_properties.GetValueProperties();
  lldbassert(global_props_sp);

  auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
  return std::static_pointer_cast<OptionValueProperties>(copy_sp);
}

OptionValueSP
OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
  auto copy_sp = OptionValue::DeepCopy(new_parent);
  // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
  // types that override GetType returning a different value.
  auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
  lldbassert(props_value_ptr);

  for (auto &property : props_value_ptr->m_properties) {
    // Duplicate any values that are not global when constructing properties
    // from a global copy.
    if (!property.IsGlobal()) {
      auto value_sp = property.GetValue()->DeepCopy(copy_sp);
      property.SetOptionValue(value_sp);
    }
  }
  return copy_sp;
}

const Property *
OptionValueProperties::GetPropertyAtPath(const ExecutionContext *exe_ctx,
                                         llvm::StringRef name) const {
  if (name.empty())
    return nullptr;

  const Property *property = nullptr;
  llvm::StringRef sub_name;
  llvm::StringRef key;
  size_t key_len = name.find_first_of(".[{");

  if (key_len != llvm::StringRef::npos) {
    key = name.take_front(key_len);
    sub_name = name.drop_front(key_len);
  } else
    key = name;

  property = GetProperty(key, exe_ctx);
  if (sub_name.empty() || !property)
    return property;

  if (sub_name[0] == '.') {
    OptionValueProperties *sub_properties =
        property->GetValue()->GetAsProperties();
    if (sub_properties)
      return sub_properties->GetPropertyAtPath(exe_ctx, sub_name.drop_front());
  }
  return nullptr;
}

void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
                                                Stream &strm) const {
  size_t max_name_len = 0;
  const size_t num_properties = m_properties.size();
  for (size_t i = 0; i < num_properties; ++i) {
    const Property *property = ProtectedGetPropertyAtIndex(i);
    if (property)
      max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
  }
  for (size_t i = 0; i < num_properties; ++i) {
    const Property *property = ProtectedGetPropertyAtIndex(i);
    if (property)
      property->DumpDescription(interpreter, strm, max_name_len, false);
  }
}

void OptionValueProperties::Apropos(
    llvm::StringRef keyword,
    std::vector<const Property *> &matching_properties) const {
  const size_t num_properties = m_properties.size();
  StreamString strm;
  for (size_t i = 0; i < num_properties; ++i) {
    const Property *property = ProtectedGetPropertyAtIndex(i);
    if (property) {
      const OptionValueProperties *properties =
          property->GetValue()->GetAsProperties();
      if (properties) {
        properties->Apropos(keyword, matching_properties);
      } else {
        bool match = false;
        llvm::StringRef name = property->GetName();
        if (name.contains_insensitive(keyword))
          match = true;
        else {
          llvm::StringRef desc = property->GetDescription();
          if (desc.contains_insensitive(keyword))
            match = true;
        }
        if (match) {
          matching_properties.push_back(property);
        }
      }
    }
  }
}

lldb::OptionValuePropertiesSP
OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
                                      llvm::StringRef name) {
  lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name));
  if (option_value_sp) {
    OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
    if (ov_properties)
      return ov_properties->shared_from_this();
  }
  return lldb::OptionValuePropertiesSP();
}

bool OptionValueProperties::VerifyPath() {
  OptionValueSP parent = GetParent();
  if (!parent) {
    // Only the top level value should have an empty path.
    return m_expected_path.empty();
  }
  OptionValueProperties *parent_properties = parent->GetAsProperties();
  if (!parent_properties)
    return false;

  auto [prefix, expected_name] = llvm::StringRef(m_expected_path).rsplit('.');

  if (expected_name.empty()) {
    // There is no dot, so the parent should be the top-level (core properties).
    return parent_properties->m_expected_path.empty() && GetName() == prefix;
  }

  return parent_properties->m_expected_path == prefix &&
         GetName() == expected_name;
}
