//===-- OptionValueProperties.cpp ---------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Interpreter/OptionValueProperties.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Flags.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Interpreter/Property.h"

using namespace lldb;
using namespace lldb_private;


OptionValueProperties::OptionValueProperties (const ConstString &name) :
    OptionValue (),
    m_name (name),
    m_properties (),
    m_name_to_index ()
{
}

OptionValueProperties::OptionValueProperties (const OptionValueProperties &global_properties) :
    OptionValue (global_properties),
    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 contructing properties from
        // a global copy
        if (m_properties[i].IsGlobal() == false)
        {
            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 PropertyDefinition *defs)
{
    for (size_t i=0; defs[i].name; ++i)
    {
        Property property(defs[i]);
        assert(property.IsValid());
        m_name_to_index.Append(property.GetName().GetCString(),m_properties.size());
        property.GetValue()->SetParent(shared_from_this());
        m_properties.push_back(property);
    }
    m_name_to_index.Sort();
}

void
OptionValueProperties::AppendProperty(const ConstString &name,
                                      const ConstString &desc,
                                      bool is_global,
                                      const OptionValueSP &value_sp)
{
    Property property(name, desc, is_global, value_sp);
    m_name_to_index.Append(name.GetCString(),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,
                                        const ConstString &key,
                                        bool will_modify) const
{
    lldb::OptionValueSP value_sp;
    size_t idx = m_name_to_index.Find (key.GetCString(), 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,
                                    const char *name,
                                    bool will_modify,
                                    Error &error) const
{
    lldb::OptionValueSP value_sp;
    
    if (name && name[0])
    {
        const char *sub_name = nullptr;
        ConstString key;
        size_t key_len = ::strcspn (name, ".[{");
        
        if (name[key_len])
        {
            key.SetCStringWithLength (name, key_len);
            sub_name = name + key_len;
        }
        else
            key.SetCString (name);
        
        value_sp = GetValueForKey (exe_ctx, key, will_modify);
        if (sub_name && value_sp)
        {
            switch (sub_name[0])
            {
            case '.':
                return value_sp->GetSubValue (exe_ctx, sub_name + 1, will_modify, error);
            
            case '{':
                // Predicate matching for predicates like
                // "<setting-name>{<predicate>}"
                // strings are parsed by the current OptionValueProperties subclass
                // to mean whatever they want to. For instance a subclass of
                // OptionValueProperties for a lldb_private::Target might implement:
                // "target.run-args{arch==i386}"   -- only set run args if the arch is i386
                // "target.run-args{path=/tmp/a/b/c/a.out}" -- only set run args if the path matches
                // "target.run-args{basename==test&&arch==x86_64}" -- only set run args if exectable basename is "test" and arch is "x86_64"
                if (sub_name[1])
                {
                    const char *predicate_start = sub_name + 1;
                    const char *predicate_end = strchr(predicate_start, '}');
                    if (predicate_end)
                    {
                        std::string predicate(predicate_start, predicate_end);
                        if (PredicateMatches(exe_ctx, predicate.c_str()))
                        {
                            if (predicate_end[1])
                            {
                                // Still more subvalue string to evaluate
                                return value_sp->GetSubValue (exe_ctx, predicate_end + 1, will_modify, error);
                            }
                            else
                            {
                                // We have a match!
                                break;
                            }
                        }
                    }
                }
                // Predicate didn't match or wasn't correctly formed
                value_sp.reset();
                break;
            
            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;
}

Error
OptionValueProperties::SetSubValue (const ExecutionContext *exe_ctx,
                                    VarSetOperationType op,
                                    const char *name,
                                    const char *value)
{
    Error error;
    const bool will_modify = true;
    lldb::OptionValueSP value_sp (GetSubValue (exe_ctx, name, will_modify, error));
    if (value_sp)
        error = value_sp->SetValueFromCString(value, op);
    else
    {
        if (error.AsCString() == nullptr)
            error.SetErrorStringWithFormat("invalid value path '%s'", name);
    }
    return error;
}


ConstString
OptionValueProperties::GetPropertyNameAtIndex (uint32_t idx) const
{
    const Property *property = GetPropertyAtIndex(nullptr, false, idx);
    if (property)
        return property->GetName();
    return ConstString();
    
}

const char *
OptionValueProperties::GetPropertyDescriptionAtIndex (uint32_t idx) const
{
    const Property *property = GetPropertyAtIndex(nullptr, false, idx);
    if (property)
        return property->GetDescription();
    return nullptr;
}

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

const Property *
OptionValueProperties::GetProperty (const ExecutionContext *exe_ctx, bool will_modify, const ConstString &name) const
{
    return GetPropertyAtIndex (exe_ctx, will_modify, m_name_to_index.Find (name.GetCString(), 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;
}

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;
}


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;
}

const char *
OptionValueProperties::GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *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, const char *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;
}

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


Error
OptionValueProperties::SetValueFromCString (const char *value, VarSetOperationType op)
{
    Error 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::SetValueFromCString (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();
        }
    }
}

Error
OptionValueProperties::DumpPropertyValue (const ExecutionContext *exe_ctx,
                                          Stream &strm,
                                          const char *property_path,
                                          uint32_t dump_mask)
{
    Error 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
{
    assert(!"this shouldn't happen");
    return lldb::OptionValueSP();
}

const Property *
OptionValueProperties::GetPropertyAtPath (const ExecutionContext *exe_ctx,
                                          bool will_modify,
                                          const char *name) const
{
    const Property *property = nullptr;
    if (name && name[0])
    {
        const char *sub_name = nullptr;
        ConstString key;
        size_t key_len = ::strcspn (name, ".[{");
        
        if (name[key_len])
        {
            key.SetCStringWithLength (name, key_len);
            sub_name = name + key_len;
        }
        else
            key.SetCString (name);
        
        property = GetProperty (exe_ctx, will_modify, key);
        if (sub_name && property)
        {
            if (sub_name[0] == '.')
            {
                OptionValueProperties *sub_properties = property->GetValue()->GetAsProperties();
                if (sub_properties)
                    return sub_properties->GetPropertyAtPath(exe_ctx, will_modify, sub_name + 1);
            }
            property = nullptr;
        }
    }
    return property;
}

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().GetLength(), 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 (const char *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;
                const char *name = property->GetName().GetCString();
                if (name && ::strcasestr(name, keyword))
                    match = true;
                else
                {
                    const char *desc = property->GetDescription();
                    if (desc && ::strcasestr(desc, keyword))
                        match = true;
                }
                if (match)
                {
                    matching_properties.push_back (property);
                }
            }
        }
    }
}

lldb::OptionValuePropertiesSP
OptionValueProperties::GetSubProperty (const ExecutionContext *exe_ctx,
                                       const 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();
}



