//===-- OptionValueFileSpecList.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/OptionValueFileSpecList.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
OptionValueFileSpecList::DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask)
{
    if (dump_mask & eDumpOptionType)
        strm.Printf ("(%s)", GetTypeAsCString ());
    if (dump_mask & eDumpOptionValue)
    {
        if (dump_mask & eDumpOptionType)
            strm.Printf (" =%s", m_current_value.GetSize() > 0 ? "\n" : "");
        strm.IndentMore();
        const uint32_t size = m_current_value.GetSize();
        for (uint32_t i = 0; i<size; ++i)
        {
            strm.Indent();
            strm.Printf("[%u]: ", i);
            m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
        }
        strm.IndentLess();
    }
}

Error
OptionValueFileSpecList::SetValueFromCString (const char *value, VarSetOperationType op)
{
    Error error;
    Args args(value);
    const size_t argc = args.GetArgumentCount();

    switch (op)
    {
        case eVarSetOperationClear:
            Clear ();
            break;
            
        case eVarSetOperationReplace:
            if (argc > 1)
            {
                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
                const uint32_t count = m_current_value.GetSize();
                if (idx > count)
                {
                    error.SetErrorStringWithFormat("invalid file list index %u, index must be 0 through %u", idx, count);
                }
                else
                {
                    for (size_t i=1; i<argc; ++i, ++idx)
                    {
                        FileSpec file (args.GetArgumentAtIndex(i), false);
                        if (idx < count)
                            m_current_value.Replace(idx, file);
                        else
                            m_current_value.Append(file);
                    }
                }
            }
            else
            {
                error.SetErrorString("replace operation takes an array index followed by one or more values");
            }
            break;
            
            
            
        case eVarSetOperationAssign:
            m_current_value.Clear();
            // Fall through to append case
        case eVarSetOperationAppend:
            if (argc > 0)
            {
                m_value_was_set = true;
                for (size_t i=0; i<argc; ++i)
                {
                    FileSpec file (args.GetArgumentAtIndex(i), false);
                    m_current_value.Append(file);
                }
            }
            else
            {
                error.SetErrorString("assign operation takes at least one file path argument");
            }
            break;
            
        case eVarSetOperationInsertBefore:
        case eVarSetOperationInsertAfter:
            if (argc > 1)
            {
                uint32_t idx = Args::StringToUInt32(args.GetArgumentAtIndex(0), UINT32_MAX);
                const uint32_t count = m_current_value.GetSize();
                if (idx > count)
                {
                    error.SetErrorStringWithFormat("invalid insert file list index %u, index must be 0 through %u", idx, count);
                }
                else
                {
                    if (op == eVarSetOperationInsertAfter)
                        ++idx;
                    for (size_t i=1; i<argc; ++i, ++idx)
                    {
                        FileSpec file (args.GetArgumentAtIndex(i), false);
                        m_current_value.Insert (idx, file);
                    }
                }
            }
            else
            {
                error.SetErrorString("insert operation takes an array index followed by one or more values");
            }
            break;
            
        case eVarSetOperationRemove:
            if (argc > 0)
            {
                std::vector<int> remove_indexes;
                bool all_indexes_valid = true;
                size_t i;
                for (i=0; all_indexes_valid && i<argc; ++i)
                {
                    const int idx = Args::StringToSInt32(args.GetArgumentAtIndex(i), INT32_MAX);
                    if (idx == INT32_MAX)
                        all_indexes_valid = false;
                    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
                        std::sort(remove_indexes.begin(), remove_indexes.end());
                        for (int j=num_remove_indexes-1; j<num_remove_indexes; ++j)
                        {
                            m_current_value.Remove (j);
                        }
                    }
                }
                else
                {
                    error.SetErrorStringWithFormat("invalid array index '%s', aborting remove operation", args.GetArgumentAtIndex(i));
                }
            }
            else
            {
                error.SetErrorString("remove operation takes one or more array index");
            }
            break;

        case eVarSetOperationInvalid:
            error = OptionValue::SetValueFromCString (value, op);
            break;
    }
    return error;

    m_value_was_set = true;
    return Error();
}

lldb::OptionValueSP
OptionValueFileSpecList::DeepCopy () const
{
    return OptionValueSP(new OptionValueFileSpecList(*this));
}


