//===-- OptionValueDictionary.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/lldb-python.h"

#include "lldb/Interpreter/OptionValueDictionary.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
// Project includes
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/OptionValueString.h"

using namespace lldb;
using namespace lldb_private;

void
OptionValueDictionary::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
    const Type dict_type = ConvertTypeMaskToType (m_type_mask);
    if (dump_mask & eDumpOptionType)
    {
        if (m_type_mask != eTypeInvalid)
            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(dict_type));
        else
            strm.Printf ("(%s)", GetTypeAsCString());
    }
    if (dump_mask & eDumpOptionValue)
    {
        if (dump_mask & eDumpOptionType)
            strm.PutCString (" =");

        collection::iterator pos, end = m_values.end();

        strm.IndentMore();
        
        for (pos = m_values.begin(); pos != end; ++pos)
        {
            OptionValue *option_value = pos->second.get();
            strm.EOL();
            strm.Indent(pos->first.GetCString());
            
            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
            switch (dict_type)
            {
                default:
                case eTypeArray:
                case eTypeDictionary:
                case eTypeProperties:
                case eTypeFileSpecList:
                case eTypePathMap:
                    strm.PutChar (' ');
                    option_value->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
                    break;

                case eTypeBoolean:
                case eTypeEnum:
                case eTypeFileSpec:
                case eTypeFormat:
                case eTypeSInt64:
                case eTypeString:
                case eTypeUInt64:
                case eTypeUUID:
                    // No need to show the type for dictionaries of simple items
                    strm.PutCString("=");
                    option_value->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
                    break;
            }
        }
        strm.IndentLess();
    }

}

size_t
OptionValueDictionary::GetArgs (Args &args) const
{
    args.Clear();
    collection::const_iterator pos, end = m_values.end();
    for (pos = m_values.begin(); pos != end; ++pos)
    {
        StreamString strm;
        strm.Printf("%s=", pos->first.GetCString());
        pos->second->DumpValue(NULL, strm, eDumpOptionValue|eDumpOptionRaw);
        args.AppendArgument(strm.GetString().c_str());
    }
    return args.GetArgumentCount();
}

Error
OptionValueDictionary::SetArgs (const Args &args, VarSetOperationType op)
{
    Error error;
    const size_t argc = args.GetArgumentCount();
    switch (op)
    {
    case eVarSetOperationClear:
        Clear();
        break;
        
    case eVarSetOperationAppend:
    case eVarSetOperationReplace:
    case eVarSetOperationAssign:
        if (argc > 0)
        {
            for (size_t i=0; i<argc; ++i)
            {
                llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
                if (!key_and_value.empty())
                {
                    std::pair<llvm::StringRef, llvm::StringRef> kvp(key_and_value.split('='));
                    llvm::StringRef key = kvp.first;
                    bool key_valid = false;
                    if (!key.empty())
                    {
                        if (key.front() == '[')
                        {
                            // Key name starts with '[', so the the key value must be in single or double quotes like:
                            // ['<key>']
                            // ["<key>"]
                            if ((key.size() > 2) && (key.back() == ']'))
                            {
                                // Strip leading '[' and trailing ']'
                                key = key.substr(1, key.size()-2);
                                const char quote_char = key.front();
                                if ((quote_char == '\'') || (quote_char == '"'))
                                {
                                    if ((key.size() > 2) && (key.back() == quote_char))
                                    {
                                        // Strip the quotes
                                        key = key.substr(1, key.size()-2);
                                        key_valid = true;
                                    }
                                }
                                else
                                {
                                    // square brackets, no quotes
                                    key_valid = true;
                                }
                            }
                        }
                        else
                        {
                            // No square brackets or quotes
                            key_valid = true;
                        }
                    }
                    if (!key_valid)
                    {
                        error.SetErrorStringWithFormat("invalid key \"%s\", the key must be a bare string or surrounded by brackets with optional quotes: [<key>] or ['<key>'] or [\"<key>\"]", kvp.first.str().c_str());
                        return error;
                    }

                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (kvp.second.data(),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        m_value_was_set = true;
                        SetValueForKey (ConstString(key), value_sp, true);
                    }
                    else
                    {
                        error.SetErrorString("dictionaries that can contain multiple types must subclass OptionValueArray");
                    }
                }
                else
                {
                    error.SetErrorString("empty argument");
                }
            }
        }
        else
        {
            error.SetErrorString("assign operation takes one or more key=value arguments");
        }
        break;
        
    case eVarSetOperationRemove:
        if (argc > 0)
        {
            for (size_t i=0; i<argc; ++i)
            {
                ConstString key(args.GetArgumentAtIndex(i));
                if (!DeleteValueForKey(key))
                {
                    error.SetErrorStringWithFormat("no value found named '%s', aborting remove operation", key.GetCString());
                    break;
                }
            }
        }
        else
        {
            error.SetErrorString("remove operation takes one or more key arguments");
        }
        break;
        
    case eVarSetOperationInsertBefore:
    case eVarSetOperationInsertAfter:
    case eVarSetOperationInvalid:
        error = OptionValue::SetValueFromCString (NULL, op);
        break;
    }
    return error;
}

Error
OptionValueDictionary::SetValueFromCString (const char *value_cstr, VarSetOperationType op)
{
    Args args(value_cstr);
    return SetArgs (args, op);
}

lldb::OptionValueSP
OptionValueDictionary::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 = NULL;
        ConstString key;
        const char *open_bracket = ::strchr (name, '[');

        if (open_bracket)
        {
            const char *key_start = open_bracket + 1;
            const char *key_end = NULL;
            switch (open_bracket[1])
            {
                case '\'':
                    ++key_start;
                    key_end = strchr(key_start, '\'');
                    if (key_end)
                    {
                        if (key_end[1] == ']')
                        {
                            if (key_end[2])
                                sub_name = key_end + 2;
                        }
                        else
                        {
                            error.SetErrorStringWithFormat ("invalid value path '%s', single quoted key names must be formatted as ['<key>'] where <key> is a string that doesn't contain quotes", name);
                            return value_sp;
                        }
                    }
                    else
                    {
                        error.SetErrorString ("missing '] key name terminator, key name started with ['");
                        return value_sp;
                    }
                    break;
                case '"':
                    ++key_start;
                    key_end = strchr(key_start, '"');
                    if (key_end)
                    {
                        if (key_end[1] == ']')
                        {
                            if (key_end[2])
                                sub_name = key_end + 2;
                            break;
                        }
                        error.SetErrorStringWithFormat ("invalid value path '%s', double quoted key names must be formatted as [\"<key>\"] where <key> is a string that doesn't contain quotes", name);
                        return value_sp;
                    }
                    else
                    {
                        error.SetErrorString ("missing \"] key name terminator, key name started with [\"");
                        return value_sp;
                    }
                    break;

                default:
                    key_end = strchr(key_start, ']');
                    if (key_end)
                    {
                        if (key_end[1])
                            sub_name = key_end + 1;
                    }
                    else
                    {
                        error.SetErrorString ("missing ] key name terminator, key name started with [");
                        return value_sp;
                    }
                    break;
            }
            
            if (key_start && key_end)
            {
                key.SetCStringWithLength (key_start, key_end - key_start);
        
                value_sp = GetValueForKey (key);
                if (value_sp)
                {
                    if (sub_name)
                        return value_sp->GetSubValue (exe_ctx, sub_name, will_modify, error);
                }
                else
                {
                    error.SetErrorStringWithFormat("dictionary does not contain a value for the key name '%s'", key.GetCString());
                }
            }
        }
        if (!value_sp && error.AsCString() == NULL)
        {
            error.SetErrorStringWithFormat ("invalid value path '%s', %s values only support '[<key>]' subvalues where <key> a string value optionally delimitted by single or double quotes",
                                            name,
                                            GetTypeAsCString());
        }
    }
    return value_sp;
}

Error
OptionValueDictionary::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() == NULL)
            error.SetErrorStringWithFormat("invalid value path '%s'", name);
    }
    return error;
}


lldb::OptionValueSP
OptionValueDictionary::GetValueForKey (const ConstString &key) const
{
    lldb::OptionValueSP value_sp;
    collection::const_iterator pos = m_values.find (key);
    if (pos != m_values.end())
        value_sp = pos->second;
    return value_sp;
}

const char *
OptionValueDictionary::GetStringValueForKey (const ConstString &key)
{
    collection::const_iterator pos = m_values.find (key);
    if (pos != m_values.end())
    {
        OptionValueString *string_value = pos->second->GetAsString();
        if (string_value)
            return string_value->GetCurrentValue();
    }
    return NULL;
}


bool
OptionValueDictionary::SetStringValueForKey (const ConstString &key, 
                                             const char *value, 
                                             bool can_replace)
{
    collection::const_iterator pos = m_values.find (key);
    if (pos != m_values.end())
    {
        if (!can_replace)
            return false;
        if (pos->second->GetType() == OptionValue::eTypeString)
        {
            pos->second->SetValueFromCString(value);
            return true;
        }
    }
    m_values[key] = OptionValueSP (new OptionValueString (value));
    return true;

}

bool
OptionValueDictionary::SetValueForKey (const ConstString &key, 
                                       const lldb::OptionValueSP &value_sp, 
                                       bool can_replace)
{
    // Make sure the value_sp object is allowed to contain
    // values of the type passed in...
    if (value_sp && (m_type_mask & value_sp->GetTypeAsMask()))
    {
        if (!can_replace)
        {
            collection::const_iterator pos = m_values.find (key);
            if (pos != m_values.end())
                return false;
        }
        m_values[key] = value_sp;
        return true;
    }
    return false;
}

bool
OptionValueDictionary::DeleteValueForKey (const ConstString &key)
{
    collection::iterator pos = m_values.find (key);
    if (pos != m_values.end())
    {
        m_values.erase(pos);
        return true;
    }
    return false;
}

lldb::OptionValueSP
OptionValueDictionary::DeepCopy () const
{
    OptionValueDictionary *copied_dict = new OptionValueDictionary (m_type_mask, m_raw_value_dump);
    lldb::OptionValueSP copied_value_sp(copied_dict);
    collection::const_iterator pos, end = m_values.end();
    for (pos = m_values.begin(); pos != end; ++pos)
    {
        StreamString strm;
        strm.Printf("%s=", pos->first.GetCString());
        copied_dict->SetValueForKey (pos->first, pos->second->DeepCopy(), true);
    }
    return copied_value_sp;
}

