//===-- OptionValueArray.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/OptionValueArray.h"

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

using namespace lldb;
using namespace lldb_private;

void
OptionValueArray::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
    const Type array_element_type = ConvertTypeMaskToType (m_type_mask);
    if (dump_mask & eDumpOptionType)
    {
        if ((GetType() == eTypeArray) && (m_type_mask != eTypeInvalid))
            strm.Printf ("(%s of %ss)", GetTypeAsCString(), GetBuiltinTypeAsCString(array_element_type));
        else
            strm.Printf ("(%s)", GetTypeAsCString());
    }
    if (dump_mask & eDumpOptionValue)
    {
        if (dump_mask & eDumpOptionType)
            strm.Printf (" =%s", (m_values.size() > 0) ? "\n" : "");
        strm.IndentMore();
        const uint32_t size = m_values.size();
        for (uint32_t i = 0; i<size; ++i)
        {
            strm.Indent();
            strm.Printf("[%u]: ", i);
            const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
            switch (array_element_type)
            {
                default:
                case eTypeArray:
                case eTypeDictionary:
                case eTypeProperties:
                case eTypeFileSpecList:
                case eTypePathMap:
                    m_values[i]->DumpValue(exe_ctx, strm, dump_mask | extra_dump_options);
                    break;
                    
                case eTypeBoolean:
                case eTypeChar:
                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
                    m_values[i]->DumpValue(exe_ctx, strm, (dump_mask & (~eDumpOptionType)) | extra_dump_options);
                    break;
            }
            if (i < (size - 1))
                strm.EOL();
        }
        strm.IndentLess();
    }
}

Error
OptionValueArray::SetValueFromCString (const char *value, VarSetOperationType op)
{
    Args args(value);
    NotifyValueChanged();
    return SetArgs (args, op);
}


lldb::OptionValueSP
OptionValueArray::GetSubValue (const ExecutionContext *exe_ctx,
                               const char *name,
                               bool will_modify,
                               Error &error) const
{
    if (name && name[0] == '[')
    {
        const char *end_bracket = strchr (name+1, ']');
        if (end_bracket)
        {
            const char *sub_value = nullptr;
            if (end_bracket[1])
                sub_value = end_bracket + 1;
            std::string index_str (name+1, end_bracket);
            const size_t array_count = m_values.size();
            int32_t idx = Args::StringToSInt32(index_str.c_str(), INT32_MAX, 0, nullptr);
            if (idx != INT32_MAX)
            {
                ;
                uint32_t new_idx = UINT32_MAX;
                if (idx < 0)
                {
                    // Access from the end of the array if the index is negative
                    new_idx = array_count - idx;
                }
                else
                {
                    // Just a standard index
                    new_idx = idx;
                }

                if (new_idx < array_count)
                {
                    if (m_values[new_idx])
                    {
                        if (sub_value)
                            return m_values[new_idx]->GetSubValue (exe_ctx, sub_value, will_modify, error);
                        else
                            return m_values[new_idx];
                    }
                }
                else
                {
                    if (array_count == 0)
                        error.SetErrorStringWithFormat("index %i is not valid for an empty array", idx);
                    else if (idx > 0)
                        error.SetErrorStringWithFormat("index %i out of range, valid values are 0 through %" PRIu64, idx, (uint64_t)(array_count - 1));
                    else
                        error.SetErrorStringWithFormat("negative index %i out of range, valid values are -1 through -%" PRIu64, idx, (uint64_t)array_count);
                }
            }
        }
    }
    else
    {
        error.SetErrorStringWithFormat("invalid value path '%s', %s values only support '[<index>]' subvalues where <index> is a positive or negative array index", name, GetTypeAsCString());
    }
    return OptionValueSP();
}


size_t
OptionValueArray::GetArgs (Args &args) const
{
    const uint32_t size = m_values.size();
    std::vector<const char *> argv;
    for (uint32_t i = 0; i<size; ++i)
    {
        const char *string_value = m_values[i]->GetStringValue ();
        if (string_value)
            argv.push_back(string_value);
    }
    
    if (argv.empty())
        args.Clear();
    else
        args.SetArguments(argv.size(), &argv[0]);
    return args.GetArgumentCount();
}

Error
OptionValueArray::SetArgs (const Args &args, VarSetOperationType op)
{
    Error error;
    const size_t argc = args.GetArgumentCount();
    switch (op)
    {
    case eVarSetOperationInvalid:
        error.SetErrorString("unsupported operation");
        break;
        
    case eVarSetOperationInsertBefore:
    case eVarSetOperationInsertAfter:
        if (argc > 1)
        {
            uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
            const uint32_t count = GetSize();
            if (idx > count)
            {
                error.SetErrorStringWithFormat("invalid insert array index %u, index must be 0 through %u", idx, count);
            }
            else
            {
                if (op == eVarSetOperationInsertAfter)
                    ++idx;
                for (size_t i=1; i<argc; ++i, ++idx)
                {
                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        if (idx >= m_values.size())
                            m_values.push_back(value_sp);
                        else
                            m_values.insert(m_values.begin() + idx, value_sp);
                    }
                    else
                    {
                        error.SetErrorString("array of complex types must subclass OptionValueArray");
                        return error;
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("insert operation takes an array index followed by one or more values");
        }
        break;
        
    case eVarSetOperationRemove:
        if (argc > 0)
        {
            const uint32_t size = m_values.size();
            std::vector<int> remove_indexes;
            bool all_indexes_valid = true;
            size_t i;
            for (i=0; i<argc; ++i)
            {
                const size_t idx =
                  Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
                if (idx >= size)
                {
                    all_indexes_valid = false;
                    break;
                }
                else
                    remove_indexes.push_back(idx);
            }
            
            if (all_indexes_valid)
            {
                size_t num_remove_indexes = remove_indexes.size();
                if (num_remove_indexes)
                {
                    // Sort and then erase in reverse so indexes are always valid
                    if (num_remove_indexes > 1)
                    {
                        std::sort(remove_indexes.begin(), remove_indexes.end());
                        for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); pos != end; ++pos)
                        {
                            m_values.erase(m_values.begin() + *pos);
                        }
                    }
                    else
                    {
                        // Only one index
                        m_values.erase(m_values.begin() + remove_indexes.front());
                    }
                }
            }
            else
            {
                error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
            }
        }
        else
        {
            error.SetErrorString("remove operation takes one or more array indices");
        }
        break;
        
    case eVarSetOperationClear:
        Clear ();
        break;
        
    case eVarSetOperationReplace:
        if (argc > 1)
        {
            uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
            const uint32_t count = GetSize();
            if (idx > count)
            {
                error.SetErrorStringWithFormat("invalid replace array index %u, index must be 0 through %u", idx, count);
            }
            else
            {
                for (size_t i=1; i<argc; ++i, ++idx)
                {
                    lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                                     m_type_mask,
                                                                                     error));
                    if (value_sp)
                    {
                        if (error.Fail())
                            return error;
                        if (idx < count)
                            m_values[idx] = value_sp;
                        else
                            m_values.push_back(value_sp);
                    }
                    else
                    {
                        error.SetErrorString("array of complex types must subclass OptionValueArray");
                        return error;
                    }
                }
            }
        }
        else
        {
            error.SetErrorString("replace operation takes an array index followed by one or more values");
        }
        break;
        
    case eVarSetOperationAssign:
        m_values.clear();
        // Fall through to append case
    case eVarSetOperationAppend:
        for (size_t i=0; i<argc; ++i)
        {
            lldb::OptionValueSP value_sp (CreateValueFromCStringForTypeMask (args.GetArgumentAtIndex(i),
                                                                             m_type_mask,
                                                                             error));
            if (value_sp)
            {
                if (error.Fail())
                    return error;
                m_value_was_set = true;
                AppendValue(value_sp);
            }
            else
            {
                error.SetErrorString("array of complex types must subclass OptionValueArray");
            }
        }
        break;
    }
    return error;
}

lldb::OptionValueSP
OptionValueArray::DeepCopy () const
{
    OptionValueArray *copied_array = new OptionValueArray (m_type_mask, m_raw_value_dump);
    lldb::OptionValueSP copied_value_sp(copied_array);
    const uint32_t size = m_values.size();
    for (uint32_t i = 0; i<size; ++i)
    {
        copied_array->AppendValue (m_values[i]->DeepCopy());
    }
    return copied_value_sp;
}



