//===-- 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/FormatManager.h"
#include "lldb/Core/State.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;
}

