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

#include "AppleObjCTypeVendor.h"

#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/ASTDumper.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"

using namespace lldb_private;

class lldb_private::AppleObjCExternalASTSource : public ClangExternalASTSourceCommon
{
public:
    AppleObjCExternalASTSource (AppleObjCTypeVendor &type_vendor) :
        m_type_vendor(type_vendor)
    {
    }

    bool
    FindExternalVisibleDeclsByName (const clang::DeclContext *decl_ctx,
                                    clang::DeclarationName name)
    {
        static unsigned int invocation_id = 0;
        unsigned int current_id = invocation_id++;

        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?

        if (log)
        {
            log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
                        current_id,
                        static_cast<void*>(&decl_ctx->getParentASTContext()),
                        name.getAsString().c_str(), decl_ctx->getDeclKindName(),
                        static_cast<const void*>(decl_ctx));
        }

        do
        {
            const clang::ObjCInterfaceDecl *interface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);

            if (!interface_decl)
                break;

            clang::ObjCInterfaceDecl *non_const_interface_decl = const_cast<clang::ObjCInterfaceDecl*>(interface_decl);

            if (!m_type_vendor.FinishDecl(non_const_interface_decl))
                break;

            clang::DeclContext::lookup_const_result result = non_const_interface_decl->lookup(name);

            return (result.size() != 0);
        }
        while(0);

        SetNoExternalVisibleDeclsForName(decl_ctx, name);
        return false;
    }

    clang::ExternalLoadResult
    FindExternalLexicalDecls (const clang::DeclContext *DC,
                              bool (*isKindWeWant)(clang::Decl::Kind),
                              llvm::SmallVectorImpl<clang::Decl*> &Decls)
    {
        return clang::ELR_Success;
    }

    void
    CompleteType (clang::TagDecl *tag_decl)
    {
        static unsigned int invocation_id = 0;
        unsigned int current_id = invocation_id++;

        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?

        if (log)
        {
            log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
                        current_id,
                        static_cast<void*>(&tag_decl->getASTContext()),
                        static_cast<void*>(tag_decl),
                        tag_decl->getName().str().c_str());

            log->Printf("  AOEAS::CT[%u] Before:", current_id);
            ASTDumper dumper((clang::Decl*)tag_decl);
            dumper.ToLog(log, "    [CT] ");
        }

        if (log)
        {
            log->Printf("  AOEAS::CT[%u] After:", current_id);
            ASTDumper dumper((clang::Decl*)tag_decl);
            dumper.ToLog(log, "    [CT] ");
        }
        return;
    }

    void
    CompleteType (clang::ObjCInterfaceDecl *interface_decl)
    {
        static unsigned int invocation_id = 0;
        unsigned int current_id = invocation_id++;

        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?

        if (log)
        {
            log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on (ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
                        current_id,
                        static_cast<void*>(&interface_decl->getASTContext()),
                        static_cast<void*>(interface_decl),
                        interface_decl->getName().str().c_str());

            log->Printf("  AOEAS::CT[%u] Before:", current_id);
            ASTDumper dumper((clang::Decl*)interface_decl);
            dumper.ToLog(log, "    [CT] ");
        }

        m_type_vendor.FinishDecl(interface_decl);

        if (log)
        {
            log->Printf("  [CT] After:");
            ASTDumper dumper((clang::Decl*)interface_decl);
            dumper.ToLog(log, "    [CT] ");
        }
        return;
    }

    bool
    layoutRecordType(const clang::RecordDecl *Record,
                     uint64_t &Size,
                     uint64_t &Alignment,
                     llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets,
                     llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
                     llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets)
    {
        return false;
    }

    void StartTranslationUnit (clang::ASTConsumer *Consumer)
    {
        clang::TranslationUnitDecl *translation_unit_decl = m_type_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
        translation_unit_decl->setHasExternalVisibleStorage();
        translation_unit_decl->setHasExternalLexicalStorage();
    }
private:
    AppleObjCTypeVendor                                    &m_type_vendor;
};

AppleObjCTypeVendor::AppleObjCTypeVendor(ObjCLanguageRuntime &runtime) :
    TypeVendor(),
    m_runtime(runtime),
    m_ast_ctx(runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple().getTriple().c_str())
{
    m_external_source = new AppleObjCExternalASTSource (*this);
    llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr (m_external_source);
    m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
}

clang::ObjCInterfaceDecl*
AppleObjCTypeVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa)
{
    ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
    
    if (iter != m_isa_to_interface.end())
        return iter->second;
    
    clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(isa);
    
    if (!descriptor)
        return NULL;
    
    const ConstString &name(descriptor->GetClassName());
    
    clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());

    clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(*ast_ctx,
                                                                                ast_ctx->getTranslationUnitDecl(),
                                                                                clang::SourceLocation(),
                                                                                &identifier_info,
                                                                                NULL);
    
    ClangASTMetadata meta_data;
    meta_data.SetISAPtr(isa);
    m_external_source->SetMetadata(new_iface_decl, meta_data);
    
    new_iface_decl->setHasExternalVisibleStorage();
    new_iface_decl->setHasExternalLexicalStorage();
    
    ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
    
    m_isa_to_interface[isa] = new_iface_decl;
    
    return new_iface_decl;
}

class ObjCRuntimeMethodType
{
public:
    ObjCRuntimeMethodType (const char *types) : m_is_valid(false)
    {
        const char *cursor = types;
        enum ParserState {
            Start = 0,
            InType,
            InPos
        } state = Start;
        const char *type = NULL;
        int brace_depth = 0;
        
        uint32_t stepsLeft = 256;
        
        while (1)
        {
            if (--stepsLeft == 0)
            {
                m_is_valid = false;
                return;
            }
            
            switch (state)
            {
            case Start:
                {
                    switch (*cursor)
                    {
                    default:
                        state = InType;
                        type = cursor;
                        break;
                    case '\0':
                        m_is_valid = true;
                        return;
                    case '0': case '1': case '2': case '3': case '4':
                    case '5': case '6': case '7': case '8': case '9':
                        m_is_valid = false;
                        return;
                    }
                }
                break;
            case InType:
                {
                    switch (*cursor)
                    {
                    default:
                        ++cursor;
                        break;
                    case '0': case '1': case '2': case '3': case '4':
                    case '5': case '6': case '7': case '8': case '9':
                        if (!brace_depth)
                        {
                            state = InPos;
                            if (type)
                            {
                                m_type_vector.push_back(std::string(type, (cursor - type)));
                            }
                            else
                            {
                                m_is_valid = false;
                                return;
                            }
                            type = NULL;
                        }
                        else
                        {
                            ++cursor;
                        }
                        break;
                    case '[': case '{': case '(':
                        ++brace_depth;
                        ++cursor;
                        break;
                    case ']': case '}': case ')':
                        if (!brace_depth)
                        {
                            m_is_valid = false;
                            return;
                        }
                        --brace_depth;
                        ++cursor;
                        break;
                    case '\0':
                        m_is_valid = false;
                        return;
                    }
                }
                break;
            case InPos:
                {
                    switch (*cursor)
                    {
                    default:
                        state = InType;
                        type = cursor;
                        break;
                    case '0': case '1': case '2': case '3': case '4':
                    case '5': case '6': case '7': case '8': case '9':
                        ++cursor;
                        break;
                    case '\0':
                        m_is_valid = true;
                        return;
                    }
                }
                break;
            }
        }
    }
    
    clang::ObjCMethodDecl *BuildMethod (clang::ObjCInterfaceDecl *interface_decl, const char *name, bool instance)
    {
        if (!m_is_valid || m_type_vector.size() < 3)
            return NULL;
        
        clang::ASTContext &ast_ctx(interface_decl->getASTContext());
        
        clang::QualType return_qual_type;
        
        const bool isInstance = instance;
        const bool isVariadic = false;
        const bool isSynthesized = false;
        const bool isImplicitlyDeclared = true;
        const bool isDefined = false;
        const clang::ObjCMethodDecl::ImplementationControl impControl = clang::ObjCMethodDecl::None;
        const bool HasRelatedResultType = false;
        
        std::vector <clang::IdentifierInfo *> selector_components;
        
        const char *name_cursor = name;
        bool is_zero_argument = true;
        
        while (*name_cursor != '\0')
        {
            const char *colon_loc = strchr(name_cursor, ':');
            if (!colon_loc)
            {
                selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
                break;
            }
            else
            {
                is_zero_argument = false;
                selector_components.push_back(&ast_ctx.Idents.get(llvm::StringRef(name_cursor, colon_loc - name_cursor)));
                name_cursor = colon_loc + 1;
            }
        }
        
        clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data());
        
        clang::QualType ret_type = BuildType(ast_ctx, m_type_vector[0].c_str());
        
        if (ret_type.isNull())
            return NULL;
        
        clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(ast_ctx,
                                                                   clang::SourceLocation(),
                                                                   clang::SourceLocation(),
                                                                   sel,
                                                                   ret_type,
                                                                   NULL,
                                                                   interface_decl,
                                                                   isInstance,
                                                                   isVariadic,
                                                                   isSynthesized,
                                                                   isImplicitlyDeclared,
                                                                   isDefined,
                                                                   impControl,
                                                                   HasRelatedResultType);
        
        std::vector <clang::ParmVarDecl*> parm_vars;
        
        for (size_t ai = 3, ae = m_type_vector.size();
             ai != ae;
             ++ai)
        {
            clang::QualType arg_type = BuildType(ast_ctx, m_type_vector[ai].c_str());
            
            if (arg_type.isNull())
                return NULL; // well, we just wasted a bunch of time.  Wish we could delete the stuff we'd just made!

            parm_vars.push_back(clang::ParmVarDecl::Create(ast_ctx,
                                                           ret,
                                                           clang::SourceLocation(),
                                                           clang::SourceLocation(),
                                                           NULL,
                                                           arg_type,
                                                           NULL,
                                                           clang::SC_None,
                                                           NULL));
        }
        
        ret->setMethodParams(ast_ctx, llvm::ArrayRef<clang::ParmVarDecl*>(parm_vars), llvm::ArrayRef<clang::SourceLocation>());
        
        return ret;
    }
private:
    clang::QualType BuildType (clang::ASTContext &ast_ctx, const char *type)
    {
        if (!type)
            return clang::QualType();
        
        switch (*type)
        {
        default:
            return ast_ctx.UnknownAnyTy;
        case 'r':
            {
                clang::QualType target_type = BuildType(ast_ctx, type+1);
                if (target_type.isNull())
                    return clang::QualType();
                else if (target_type == ast_ctx.UnknownAnyTy)
                    return ast_ctx.UnknownAnyTy;
                else
                    return ast_ctx.getConstType(target_type);
            }
        case '^':
        {
            clang::QualType target_type = BuildType(ast_ctx, type+1);
            if (target_type.isNull())
                return clang::QualType();
            else if (target_type == ast_ctx.UnknownAnyTy)
                return ast_ctx.UnknownAnyTy;
            else
                return ast_ctx.getPointerType(target_type);
        }
        case 'c':
            return ast_ctx.CharTy;
        case 'i':
            return ast_ctx.IntTy;
        case 's':
            return ast_ctx.ShortTy;
        case 'l':
            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
                return ast_ctx.IntTy;
            else
                return ast_ctx.LongTy;
        case 'q':
            return ast_ctx.LongLongTy;
        case 'C':
            return ast_ctx.UnsignedCharTy;
        case 'I':
            return ast_ctx.UnsignedIntTy;
        case 'S':
            return ast_ctx.UnsignedShortTy;
        case 'L':
            if (ast_ctx.getTypeSize(ast_ctx.VoidTy) == 64)
                return ast_ctx.UnsignedIntTy;
            else
                return ast_ctx.UnsignedLongTy;
        case 'Q':
            return ast_ctx.UnsignedLongLongTy;
        case 'f':
            return ast_ctx.FloatTy;
        case 'd':
            return ast_ctx.DoubleTy;
        case 'B':
            return ast_ctx.BoolTy;
        case 'v':
            return ast_ctx.VoidTy;
        case '*':
            return ast_ctx.getPointerType(ast_ctx.CharTy);
        case '@':
            return ast_ctx.getObjCIdType();
        case '#':
            return ast_ctx.getObjCClassType();
        case ':':
            return ast_ctx.getObjCSelType();
        }
        return clang::QualType();
    }
    
    typedef std::vector <std::string> TypeVector;
    
    TypeVector  m_type_vector;
    bool        m_is_valid;
};

bool
AppleObjCTypeVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl)
{
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?
    
    ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
    ObjCLanguageRuntime::ObjCISA objc_isa = 0;
    if (metadata)
     objc_isa = metadata->GetISAPtr();
    
    if (!objc_isa)
        return false;
    
    if (!interface_decl->hasExternalVisibleStorage())
        return true;
    
    interface_decl->startDefinition();
    
    interface_decl->setHasExternalVisibleStorage(false);
    interface_decl->setHasExternalLexicalStorage(false);
    
    ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(objc_isa);
    
    if (!descriptor)
        return false;
    
    auto superclass_func = [interface_decl, this](ObjCLanguageRuntime::ObjCISA isa)
    {
        clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
        if (!superclass_decl)
            return;
        interface_decl->setSuperClass(superclass_decl);
    };
    
    auto instance_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
    {        
        if (!name || !types)
            return false; // skip this one

        ObjCRuntimeMethodType method_type(types);
        
        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, true);
        
        if (log)
            log->Printf("[  AOTV::FD] Instance method [%s] [%s]", name, types);
        
        if (method_decl)
            interface_decl->addDecl(method_decl);
        
        return false;
    };
    
    auto class_method_func = [log, interface_decl, this](const char *name, const char *types) -> bool
    {
        if (!name || !types)
            return false; // skip this one
        
        ObjCRuntimeMethodType method_type(types);
        
        clang::ObjCMethodDecl *method_decl = method_type.BuildMethod (interface_decl, name, false);
        
        if (log)
            log->Printf("[  AOTV::FD] Class method [%s] [%s]", name, types);
        
        if (method_decl)
            interface_decl->addDecl(method_decl);
        
        return false;
    };
    
    if (log)
    {
        ASTDumper method_dumper ((clang::Decl*)interface_decl);
        
        log->Printf("[AppleObjCTypeVendor::FinishDecl] Finishing Objective-C interface for %s", descriptor->GetClassName().AsCString());
    }
    
    
    if (!descriptor->Describe(superclass_func,
                              instance_method_func,
                              class_method_func,
                              std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> (nullptr)))
        return false;
    
    if (log)
    {
        ASTDumper method_dumper ((clang::Decl*)interface_decl);
        
        log->Printf("[AppleObjCTypeVendor::FinishDecl] Finished Objective-C interface");
        
        method_dumper.ToLog(log, "  [AOTV::FD] ");
    }
    
    return true;
}

uint32_t
AppleObjCTypeVendor::FindTypes (const ConstString &name,
                                bool append,
                                uint32_t max_matches,
                                std::vector <ClangASTType> &types)
{
    static unsigned int invocation_id = 0;
    unsigned int current_id = invocation_id++;
    
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));  // FIXME - a more appropriate log channel?
    
    if (log)
        log->Printf("AppleObjCTypeVendor::FindTypes [%u] ('%s', %s, %u, )",
                    current_id,
                    (const char*)name.AsCString(),
                    append ? "true" : "false",
                    max_matches);
    
    if (!append)
        types.clear();
    
    uint32_t ret = 0;
    
    do
    {
        // See if the type is already in our ASTContext.
        
        clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
        
        clang::IdentifierInfo &identifier_info = ast_ctx->Idents.get(name.GetStringRef());
        clang::DeclarationName decl_name = ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
        
        clang::DeclContext::lookup_const_result lookup_result = ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
        
        if (!lookup_result.empty())
        {
            if (const clang::ObjCInterfaceDecl *result_iface_decl = llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0]))
            {
                clang::QualType result_iface_type = ast_ctx->getObjCInterfaceType(result_iface_decl);
                
                if (log)
                {
                    ASTDumper dumper(result_iface_type);
                    
                    uint64_t isa_value = LLDB_INVALID_ADDRESS;
                    ClangASTMetadata *metadata = m_external_source->GetMetadata(result_iface_decl);
                    if (metadata)
                        isa_value = metadata->GetISAPtr();
                    
                    log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64 ") in the ASTContext",
                                current_id,
                                dumper.GetCString(),
                                isa_value);
                }
                    
                types.push_back(ClangASTType(ast_ctx, result_iface_type.getAsOpaquePtr()));
                ret++;
                break;
            }
            else
            {
                if (log)
                    log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but it's not something we know about",
                                current_id);
                break;
            }
        }
        else if(log)
        {
            log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
                        current_id,
                        name.AsCString());
        }
        
        // It's not.  If it exists, we have to put it into our ASTContext.
                
        ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
    
        if (!isa)
        {
            if (log)
                log->Printf("AOCTV::FT [%u] Couldn't find the isa",
                            current_id);
            
            break;
        }
        
        clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
        
        if (!iface_decl)
        {
            if (log)
                log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for isa 0x%" PRIx64,
                            current_id,
                            (uint64_t)isa);
            
            break;
        }
        
        clang::QualType new_iface_type = ast_ctx->getObjCInterfaceType(iface_decl);
        
        if (log)
        {
            ASTDumper dumper(new_iface_type);
            log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
                        current_id,
                        dumper.GetCString(),
                        (uint64_t)isa);
        }
        
        types.push_back(ClangASTType(ast_ctx, new_iface_type.getAsOpaquePtr()));
        ret++;
        break;
    } while (0);
    
    return ret;
}
