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

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"

// Project includes
#include "Cocoa.h"

#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Target.h"

#include "lldb/Utility/ProcessStructReader.h"

#include "Plugins/Language/ObjC/NSString.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

static lldb::addr_t
DerefToNSErrorPointer (ValueObject& valobj)
{
    CompilerType valobj_type(valobj.GetCompilerType());
    Flags type_flags(valobj_type.GetTypeInfo());
    if (type_flags.AllClear(eTypeHasValue))
    {
        if (valobj.IsBaseClass() && valobj.GetParent())
            return valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
    }
    else
    {
        lldb::addr_t ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
        if (type_flags.AllSet(eTypeIsPointer))
        {
            CompilerType pointee_type(valobj_type.GetPointeeType());
            Flags pointee_flags(pointee_type.GetTypeInfo());
            if (pointee_flags.AllSet(eTypeIsPointer))
            {
                if (ProcessSP process_sp = valobj.GetProcessSP())
                {
                    Error error;
                    ptr_value = process_sp->ReadPointerFromMemory(ptr_value, error);
                }
            }
        }
        return ptr_value;
    }
    
    return LLDB_INVALID_ADDRESS;
}

bool
lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
{
    ProcessSP process_sp(valobj.GetProcessSP());
    if (!process_sp)
        return false;
    
    lldb::addr_t ptr_value = DerefToNSErrorPointer(valobj);
    if (ptr_value == LLDB_INVALID_ADDRESS)
        return false;

    size_t ptr_size = process_sp->GetAddressByteSize();
    lldb::addr_t code_location = ptr_value + 2 * ptr_size;
    lldb::addr_t domain_location = ptr_value + 3 * ptr_size;
    
    Error error;
    uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error);
    if (error.Fail())
        return false;
    
    lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error);
    if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS)
        return false;
    
    if (!domain_str_value)
    {
        stream.Printf("domain: nil - code: %" PRIu64, code);
        return true;
    }
    
    InferiorSizedWord isw(domain_str_value, *process_sp);
    
    ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType());
    
    if (!domain_str_sp)
        return false;
    
    StreamString domain_str_summary;
    if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty())
    {
        stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code);
        return true;
    }
    else
    {
        stream.Printf("domain: nil - code: %" PRIu64, code);
        return true;
    }
}

class NSErrorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
    NSErrorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
    SyntheticChildrenFrontEnd(*valobj_sp)
    {}

    ~NSErrorSyntheticFrontEnd() override = default;
    // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf

    size_t
    CalculateNumChildren() override
    {
        if (m_child_ptr)
            return 1;
        if (m_child_sp)
            return 1;
        return 0;
    }
    
    lldb::ValueObjectSP
    GetChildAtIndex(size_t idx) override
    {
        if (idx != 0)
            return lldb::ValueObjectSP();
        
        if (m_child_ptr)
            return m_child_ptr->GetSP();
        return m_child_sp;
    }
    
    bool
    Update() override
    {
        m_child_ptr = nullptr;
        m_child_sp.reset();
        
        ProcessSP process_sp(m_backend.GetProcessSP());
        if (!process_sp)
            return false;
        
        lldb::addr_t userinfo_location = DerefToNSErrorPointer(m_backend);
        if (userinfo_location == LLDB_INVALID_ADDRESS)
            return false;
        
        size_t ptr_size = process_sp->GetAddressByteSize();

        userinfo_location += 4 * ptr_size;
        Error error;
        lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error);
        if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
            return false;
        InferiorSizedWord isw(userinfo,*process_sp);
        m_child_sp = CreateValueObjectFromData("_userInfo",
                                               isw.GetAsData(process_sp->GetByteOrder()),
                                               m_backend.GetExecutionContextRef(),
                                               process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID));
        return false;
    }
    
    bool
    MightHaveChildren() override
    {
        return true;
    }
    
    size_t
    GetIndexOfChildWithName(const ConstString &name) override
    {
        static ConstString g___userInfo("_userInfo");
        if (name == g___userInfo)
            return 0;
        return UINT32_MAX;
    }

private:
    // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory
    // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak
    // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away
    // oh joy!
    ValueObject* m_child_ptr;
    ValueObjectSP m_child_sp;
};

SyntheticChildrenFrontEnd*
lldb_private::formatters::NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
{
    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
    if (!process_sp)
        return nullptr;
    ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
    if (!runtime)
        return nullptr;
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
    
    if (!descriptor.get() || !descriptor->IsValid())
        return nullptr;
    
    const char* class_name = descriptor->GetClassName().GetCString();
    
    if (!class_name || !*class_name)
        return nullptr;
    
    if (!strcmp(class_name,"NSError"))
        return (new NSErrorSyntheticFrontEnd(valobj_sp));
    else if (!strcmp(class_name,"__NSCFError"))
        return (new NSErrorSyntheticFrontEnd(valobj_sp));
    
    return nullptr;
}
