//===-- 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(ConstString name) : m_name(name) {}

size_t OptionValueProperties::GetNumProperties() const {
  return m_properties.size();
}

void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
  for (const auto &definition : defs) {
    Property property(definition);
    assert(property.IsValid());
    m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
    property.GetValue()->SetParent(shared_from_this());
    m_properties.push_back(property);
  }
  m_name_to_index.Sort();
}

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

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

// bool
// OptionValueProperties::GetQualifiedName (Stream &strm)
//{
//    bool dumped_something = false;
////    lldb::OptionValuePropertiesSP parent_sp(GetParent ());
////    if (parent_sp)
////    {
////        parent_sp->GetQualifiedName (strm);
////        strm.PutChar('.');
////        dumped_something = true;
////    }
//    if (m_name)
//    {
//        strm << m_name;
//        dumped_something = true;
//    }
//    return dumped_something;
//}
//
lldb::OptionValueSP
OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
                                      ConstString key,
                                      bool will_modify) const {
  lldb::OptionValueSP value_sp;
  size_t idx = m_name_to_index.Find(key, SIZE_MAX);
  if (idx < m_properties.size())
    value_sp = GetPropertyAtIndex(exe_ctx, will_modify, idx)->GetValue();
  return value_sp;
}

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

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

  value_sp = GetValueForKey(exe_ctx, key, will_modify);
  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(), will_modify, error);
    if (!return_val_sp) {
      if (Properties::IsSettingExperimental(sub_name.drop_front())) {
        size_t experimental_len =
            strlen(Properties::GetExperimentalSettingsName());
        if (sub_name[experimental_len + 1] == '.')
          return_val_sp = value_sp->GetSubValue(
              exe_ctx, sub_name.drop_front(experimental_len + 2), will_modify, 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, will_modify, 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;
  const bool will_modify = true;
  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, will_modify, 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.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
    }
  }
  return error;
}

uint32_t
OptionValueProperties::GetPropertyIndex(ConstString name) const {
  return m_name_to_index.Find(name, SIZE_MAX);
}

const Property *
OptionValueProperties::GetProperty(const ExecutionContext *exe_ctx,
                                   bool will_modify,
                                   ConstString name) const {
  return GetPropertyAtIndex(
      exe_ctx, will_modify,
      m_name_to_index.Find(name, SIZE_MAX));
}

const Property *OptionValueProperties::GetPropertyAtIndex(
    const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const {
  return ProtectedGetPropertyAtIndex(idx);
}

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

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

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

OptionValueArch *OptionValueProperties::GetPropertyAtIndexAsOptionValueArch(
    const ExecutionContext *exe_ctx, uint32_t idx) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property)
    return property->GetValue()->GetAsArch();
  return nullptr;
}

OptionValueLanguage *
OptionValueProperties::GetPropertyAtIndexAsOptionValueLanguage(
    const ExecutionContext *exe_ctx, uint32_t idx) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property)
    return property->GetValue()->GetAsLanguage();
  return nullptr;
}

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

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

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

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

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

  return false;
}

bool OptionValueProperties::SetPropertyAtIndexFromArgs(
    const ExecutionContext *exe_ctx, uint32_t idx, const Args &args) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  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;
}

bool OptionValueProperties::GetPropertyAtIndexAsBoolean(
    const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetBooleanValue(fail_value);
  }
  return fail_value;
}

bool OptionValueProperties::SetPropertyAtIndexAsBoolean(
    const ExecutionContext *exe_ctx, uint32_t idx, bool new_value) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value) {
      value->SetBooleanValue(new_value);
      return true;
    }
  }
  return false;
}

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

int64_t OptionValueProperties::GetPropertyAtIndexAsEnumeration(
    const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetEnumerationValue(fail_value);
  }
  return fail_value;
}

bool OptionValueProperties::SetPropertyAtIndexAsEnumeration(
    const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->SetEnumerationValue(new_value);
  }
  return false;
}

const FormatEntity::Entry *
OptionValueProperties::GetPropertyAtIndexAsFormatEntity(
    const ExecutionContext *exe_ctx, uint32_t idx) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetFormatEntity();
  }
  return nullptr;
}

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

FileSpec OptionValueProperties::GetPropertyAtIndexAsFileSpec(
    const ExecutionContext *exe_ctx, uint32_t idx) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetFileSpecValue();
  }
  return FileSpec();
}

bool OptionValueProperties::SetPropertyAtIndexAsFileSpec(
    const ExecutionContext *exe_ctx, uint32_t idx,
    const FileSpec &new_file_spec) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->SetFileSpecValue(new_file_spec);
  }
  return false;
}

const RegularExpression *
OptionValueProperties::GetPropertyAtIndexAsOptionValueRegex(
    const ExecutionContext *exe_ctx, uint32_t idx) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetRegexValue();
  }
  return nullptr;
}

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

int64_t OptionValueProperties::GetPropertyAtIndexAsSInt64(
    const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetSInt64Value(fail_value);
  }
  return fail_value;
}

bool OptionValueProperties::SetPropertyAtIndexAsSInt64(
    const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->SetSInt64Value(new_value);
  }
  return false;
}

llvm::StringRef OptionValueProperties::GetPropertyAtIndexAsString(
    const ExecutionContext *exe_ctx, uint32_t idx,
    llvm::StringRef fail_value) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetStringValue(fail_value);
  }
  return fail_value;
}

bool OptionValueProperties::SetPropertyAtIndexAsString(
    const ExecutionContext *exe_ctx, uint32_t idx, llvm::StringRef new_value) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->SetStringValue(new_value);
  }
  return false;
}

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

uint64_t OptionValueProperties::GetPropertyAtIndexAsUInt64(
    const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const {
  const Property *property = GetPropertyAtIndex(exe_ctx, false, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->GetUInt64Value(fail_value);
  }
  return fail_value;
}

bool OptionValueProperties::SetPropertyAtIndexAsUInt64(
    const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value) {
  const Property *property = GetPropertyAtIndex(exe_ctx, true, idx);
  if (property) {
    OptionValue *value = property->GetValue().get();
    if (value)
      return value->SetUInt64Value(new_value);
  }
  return false;
}

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(exe_ctx, false, i);
    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();
    }
  }
}

Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
                                                Stream &strm,
                                                llvm::StringRef property_path,
                                                uint32_t dump_mask) {
  Status error;
  const bool will_modify = false;
  lldb::OptionValueSP value_sp(
      GetSubValue(exe_ctx, property_path, will_modify, error));
  if (value_sp) {
    if (!value_sp->ValueIsTransparent()) {
      if (dump_mask & eDumpOptionName)
        strm.PutCString(property_path);
      if (dump_mask & ~eDumpOptionName)
        strm.PutChar(' ');
    }
    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, bool will_modify, llvm::StringRef name) const {
  const Property *property = nullptr;
  if (name.empty())
    return nullptr;
  llvm::StringRef sub_name;
  ConstString key;
  size_t key_len = name.find_first_of(".[{");

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

  property = GetProperty(exe_ctx, will_modify, key);
  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, will_modify,
                                                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,
                                      ConstString name) {
  lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name, false));
  if (option_value_sp) {
    OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
    if (ov_properties)
      return ov_properties->shared_from_this();
  }
  return lldb::OptionValuePropertiesSP();
}
