//===-- 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)
    : OptionValue(), m_name(name), m_properties(), m_name_to_index() {}

OptionValueProperties::OptionValueProperties(
    const OptionValueProperties &global_properties)
    : OptionValue(global_properties),
      std::enable_shared_from_this<OptionValueProperties>(),
      m_name(global_properties.m_name),
      m_properties(global_properties.m_properties),
      m_name_to_index(global_properties.m_name_to_index) {
  // We now have an exact copy of "global_properties". We need to now find all
  // non-global settings and copy the property values so that all non-global
  // settings get new OptionValue instances created for them.
  const size_t num_properties = m_properties.size();
  for (size_t i = 0; i < num_properties; ++i) {
    // Duplicate any values that are not global when constructing properties
    // from a global copy
    if (!m_properties[i].IsGlobal()) {
      lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
      m_properties[i].SetOptionValue(new_value_sp);
    }
  }
}

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, desc, 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) {
    OptionValue *value = property->GetValue().get();
    if (value) {
      const OptionValueArray *array = value->GetAsArray();
      if (array)
        return array->GetArgs(args);
      else {
        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) {
    OptionValue *value = property->GetValue().get();
    if (value) {
      OptionValueArray *array = value->GetAsArray();
      if (array)
        return array->SetArgs(args, eVarSetOperationAssign).Success();
      else {
        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;
}

lldb::OptionValueSP OptionValueProperties::DeepCopy() const {
  llvm_unreachable("this shouldn't happen");
}

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_lower(keyword))
          match = true;
        else {
          llvm::StringRef desc = property->GetDescription();
          if (desc.contains_lower(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();
}
