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

#include <sstream>

#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/JavaASTContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/Target.h"

#include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h"

using namespace lldb;
using namespace lldb_private;

namespace lldb_private
{

class JavaASTContext::JavaType
{
public:
    enum LLVMCastKind
    {
        eKindPrimitive,
        eKindObject,
        eKindReference,
        eKindArray,
        kNumKinds
    };

    JavaType(LLVMCastKind kind) : m_kind(kind) {}

    virtual ~JavaType() = default;

    virtual ConstString
    GetName() = 0;

    virtual void
    Dump(Stream *s) = 0;

    virtual bool
    IsCompleteType() = 0;

    LLVMCastKind
    getKind() const
    {
        return m_kind;
    }

private:
    LLVMCastKind m_kind;
};

} // end of namespace lldb_private

namespace
{

class JavaPrimitiveType : public JavaASTContext::JavaType
{
public:
    enum TypeKind
    {
        eTypeByte,
        eTypeShort,
        eTypeInt,
        eTypeLong,
        eTypeFloat,
        eTypeDouble,
        eTypeBoolean,
        eTypeChar,
    };

    JavaPrimitiveType(TypeKind type_kind) : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {}

    ConstString
    GetName() override
    {
        switch (m_type_kind)
        {
            case eTypeByte:
                return ConstString("byte");
            case eTypeShort:
                return ConstString("short");
            case eTypeInt:
                return ConstString("int");
            case eTypeLong:
                return ConstString("long");
            case eTypeFloat:
                return ConstString("float");
            case eTypeDouble:
                return ConstString("double");
            case eTypeBoolean:
                return ConstString("boolean");
            case eTypeChar:
                return ConstString("char");
        }
        return ConstString();
    }

    TypeKind
    GetTypeKind()
    {
        return m_type_kind;
    }

    void
    Dump(Stream *s) override
    {
        s->Printf("%s\n", GetName().GetCString());
    }

    bool
    IsCompleteType() override
    {
        return true;
    }

    static bool
    classof(const JavaType *jt)
    {
        return jt->getKind() == JavaType::eKindPrimitive;
    }

private:
    const TypeKind m_type_kind;
};

class JavaDynamicType : public JavaASTContext::JavaType
{
public:
    JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) :
        JavaType(kind),
        m_linkage_name(linkage_name),
        m_dynamic_type_id(nullptr)
    {
    }

    ConstString
    GetLinkageName() const
    {
        return m_linkage_name;
    }

    void
    SetDynamicTypeId(const DWARFExpression &type_id)
    {
        m_dynamic_type_id = type_id;
    }

    uint64_t
    CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj)
    {
        if (!m_dynamic_type_id.IsValid())
            return UINT64_MAX;

        Value obj_load_address = value_obj.GetValue();
        obj_load_address.ResolveValue(exe_ctx);
        obj_load_address.SetValueType(Value::eValueTypeLoadAddress);

        Value result;
        if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address,
                                       nullptr, result, nullptr))
        {
            Error error;

            lldb::addr_t type_id_addr = result.GetScalar().UInt();
            lldb::ProcessSP process_sp = exe_ctx->GetProcessSP();
            if (process_sp)
                return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(),
                                                                 UINT64_MAX, error);
        }

        return UINT64_MAX;
    }

public:
    ConstString m_linkage_name;
    DWARFExpression m_dynamic_type_id;
};

class JavaObjectType : public JavaDynamicType
{
public:
    struct Field
    {
        ConstString m_name;
        CompilerType m_type;
        uint32_t m_offset;
    };

    JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size)
        : JavaDynamicType(JavaType::eKindObject, linkage_name),
          m_name(name),
          m_byte_size(byte_size),
          m_base_class_offset(0),
          m_is_complete(false)
    {
    }

    ConstString
    GetName() override
    {
        return m_name;
    }

    uint32_t
    GetByteSize() const
    {
        return m_byte_size;
    }

    uint32_t
    GetNumFields()
    {
        return m_fields.size();
    }

    void
    Dump(Stream *s) override
    {
        if (m_base_class.IsValid())
            s->Printf("%s : %s\n", GetName().GetCString(), m_base_class.GetTypeName().GetCString());
        else
            s->Printf("%s\n", GetName().GetCString());

        s->IndentMore();
        for (const Field &f : m_fields)
            s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(), f.m_name.GetCString());
        s->IndentLess();
    }

    Field *
    GetFieldAtIndex(size_t idx)
    {
        if (idx < m_fields.size())
            return &m_fields[idx];
        return nullptr;
    }

    CompilerType
    GetBaseClass()
    {
        return m_base_class;
    }

    uint32_t
    GetBaseClassOffset()
    {
        return m_base_class_offset;
    }

    uint32_t
    GetNumInterfaces()
    {
        return m_interfaces.size();
    }

    CompilerType
    GetInterfaceAtIndex(uint32_t idx)
    {
        if (m_interfaces.size() < idx)
            return m_interfaces[idx];
        return CompilerType();
    }

    bool
    IsCompleteType() override
    {
        return m_is_complete;
    }

    void
    SetCompleteType(bool is_complete)
    {
        m_is_complete = is_complete;
        if (m_byte_size == 0)
        {
            // Try to calcualte the size of the object based on it's values
            for (const Field &field : m_fields)
            {
                uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr);
                if (field_end > m_byte_size)
                    m_byte_size = field_end;
            }
        }
    }

    void
    AddBaseClass(const CompilerType &type, uint32_t offset)
    {
        // TODO: Check if type is an interface and add it to the interface list in that case
        m_base_class = type;
        m_base_class_offset = offset;
    }

    void
    AddField(const ConstString &name, const CompilerType &type, uint32_t offset)
    {
        m_fields.push_back({name, type, offset});
    }

    static bool
    classof(const JavaType *jt)
    {
        return jt->getKind() == JavaType::eKindObject;
    }

private:
    ConstString m_name;
    uint32_t m_byte_size;
    CompilerType m_base_class;
    uint32_t m_base_class_offset;
    std::vector<CompilerType> m_interfaces;
    std::vector<Field> m_fields;
    bool m_is_complete;
};

class JavaReferenceType : public JavaASTContext::JavaType
{
public:
    JavaReferenceType(CompilerType pointee_type) : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {}

    static bool
    classof(const JavaType *jt)
    {
        return jt->getKind() == JavaType::eKindReference;
    }

    CompilerType
    GetPointeeType()
    {
        return m_pointee_type;
    }

    ConstString
    GetName() override
    {
        ConstString pointee_type_name = static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType())->GetName();
        return ConstString(std::string(pointee_type_name.AsCString()) + "&");
    }

    void
    Dump(Stream *s) override
    {
        static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s);
    }

    bool
    IsCompleteType() override
    {
        return m_pointee_type.IsCompleteType();
    }

private:
    CompilerType m_pointee_type;
};

class JavaArrayType : public JavaDynamicType
{
public:
    JavaArrayType(const ConstString& linkage_name, CompilerType element_type, const DWARFExpression &length_expression,
                  lldb::addr_t data_offset)
        : JavaDynamicType(JavaType::eKindArray, linkage_name),
          m_element_type(element_type),
          m_length_expression(length_expression),
          m_data_offset(data_offset)
    {
    }

    static bool
    classof(const JavaType *jt)
    {
        return jt->getKind() == JavaType::eKindArray;
    }

    CompilerType
    GetElementType()
    {
        return m_element_type;
    }

    ConstString
    GetName() override
    {
        ConstString element_type_name = static_cast<JavaType *>(GetElementType().GetOpaqueQualType())->GetName();
        return ConstString(std::string(element_type_name.AsCString()) + "[]");
    }

    void
    Dump(Stream *s) override
    {
        s->Printf("%s\n", GetName().GetCString());
    }

    bool
    IsCompleteType() override
    {
        return m_length_expression.IsValid();
    }

    uint32_t
    GetNumElements(ValueObject *value_obj)
    {
        if (!m_length_expression.IsValid())
            return UINT32_MAX;

        Error error;
        ValueObjectSP address_obj = value_obj->AddressOf(error);
        if (error.Fail())
            return UINT32_MAX;

        Value obj_load_address = address_obj->GetValue();
        obj_load_address.SetValueType(Value::eValueTypeLoadAddress);

        Value result;
        ExecutionContextScope* exec_ctx_scope = value_obj->GetExecutionContextRef().Lock(true).GetBestExecutionContextScope();
        if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, nullptr, &obj_load_address, result, nullptr))
            return result.GetScalar().UInt();

        return UINT32_MAX;
    }

    uint64_t
    GetElementOffset(size_t idx)
    {
        return m_data_offset + idx * m_element_type.GetByteSize(nullptr);
    }

private:
    CompilerType m_element_type;
    DWARFExpression m_length_expression;
    lldb::addr_t m_data_offset;
};

} // end of anonymous namespace

ConstString
JavaASTContext::GetPluginNameStatic()
{
    return ConstString("java");
}

ConstString
JavaASTContext::GetPluginName()
{
    return JavaASTContext::GetPluginNameStatic();
}

uint32_t
JavaASTContext::GetPluginVersion()
{
    return 1;
}

lldb::TypeSystemSP
JavaASTContext::CreateInstance(lldb::LanguageType language, Module *module, Target *target)
{
    if (language == eLanguageTypeJava)
    {
        if (module)
            return std::make_shared<JavaASTContext>(module->GetArchitecture());
        if (target)
            return std::make_shared<JavaASTContext>(target->GetArchitecture());
        assert(false && "Either a module or a target has to be specifed to create a JavaASTContext");
    }
    return lldb::TypeSystemSP();
}

void
JavaASTContext::EnumerateSupportedLanguages(std::set<lldb::LanguageType> &languages_for_types,
                                            std::set<lldb::LanguageType> &languages_for_expressions)
{
    static std::vector<lldb::LanguageType> s_languages_for_types({lldb::eLanguageTypeJava});
    static std::vector<lldb::LanguageType> s_languages_for_expressions({});

    languages_for_types.insert(s_languages_for_types.begin(), s_languages_for_types.end());
    languages_for_expressions.insert(s_languages_for_expressions.begin(), s_languages_for_expressions.end());
}

void
JavaASTContext::Initialize()
{
    PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in", CreateInstance,
                                  EnumerateSupportedLanguages);
}

void
JavaASTContext::Terminate()
{
    PluginManager::UnregisterPlugin(CreateInstance);
}

JavaASTContext::JavaASTContext(const ArchSpec &arch)
    : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize())
{
}

JavaASTContext::~JavaASTContext()
{
}

uint32_t
JavaASTContext::GetPointerByteSize()
{
    return m_pointer_byte_size;
}

DWARFASTParser *
JavaASTContext::GetDWARFParser()
{
    if (!m_dwarf_ast_parser_ap)
        m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this));
    return m_dwarf_ast_parser_ap.get();
}

ConstString
JavaASTContext::DeclGetName(void *opaque_decl)
{
    return ConstString();
}

std::vector<CompilerDecl>
JavaASTContext::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls)
{
    return std::vector<CompilerDecl>();
}

bool
JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx)
{
    return false;
}

ConstString
JavaASTContext::DeclContextGetName(void *opaque_decl_ctx)
{
    return ConstString();
}

bool
JavaASTContext::DeclContextIsClassMethod(void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
                                         bool *is_instance_method_ptr, ConstString *language_object_name_ptr)
{
    return false;
}

bool
JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size,
                            bool *is_incomplete)
{
    if (element_type)
        element_type->Clear();
    if (size)
        *size = 0;
    if (is_incomplete)
        *is_incomplete = false;

    if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type)))
    {
        if (element_type)
            *element_type = array->GetElementType();
        return true;
    }
    return false;
}

bool
JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type)
{
    return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
}

bool
JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type)
{
    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
        return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar;
    return false;
}

bool
JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, bool &is_complex)
{
    is_complex = true;

    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeFloat:
            case JavaPrimitiveType::eTypeDouble:
                count = 1;
                return true;
            default:
                break;
        }
    }

    count = 0;
    return false;
}

bool
JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type, bool *is_variadic_ptr)
{
    if (is_variadic_ptr)
        *is_variadic_ptr = false;
    return false;
}

size_t
JavaASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type)
{
    return 0;
}

CompilerType
JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, const size_t index)
{
    return CompilerType();
}

bool
JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type)
{
    return false;
}

bool
JavaASTContext::IsBlockPointerType (lldb::opaque_compiler_type_t type, CompilerType *function_pointer_type_ptr)
{
    return false;
}

bool
JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed)
{
    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
            case JavaPrimitiveType::eTypeShort:
            case JavaPrimitiveType::eTypeInt:
            case JavaPrimitiveType::eTypeLong:
                is_signed = true;
                return true;
            default:
                break;
        }
    }

    is_signed = false;
    return false;
}

bool
JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type, CompilerType *target_type,
                                      bool check_cplusplus, bool check_objc)
{
    return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type));
}

bool
JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
{
    if (pointee_type)
        pointee_type->Clear();
    return false;
}

bool
JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type, bool *is_rvalue)
{
    if (is_rvalue)
        *is_rvalue = false;

    if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
    {
        if (pointee_type)
            *pointee_type = ref->GetPointeeType();
        return true;
    }

    if (pointee_type)
        pointee_type->Clear();
    return false;
}

bool
JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type)
{
    return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) ||
           llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type));
}

bool
JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type)
{
    return false; // TODO: Implement if we introduce the void type
}

bool
JavaASTContext::SupportsLanguage(lldb::LanguageType language)
{
    return language == lldb::eLanguageTypeJava;
}

bool
JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type)
{
    return true;
}

bool
JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, CompilerType *pointee_type)
{
    return IsPointerType(type, pointee_type) || IsReferenceType(type, pointee_type);
}

bool
JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type, uint32_t &length)
{
    return false; // TODO: Implement it if we need it for string literals
}

bool
JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type)
{
    return false;
}

bool
JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type, CompilerType *element_type, uint64_t *size)
{
    if (element_type)
        element_type->Clear();
    if (size)
        *size = 0;
    return false;
}

bool
JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type)
{
    return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
}

uint32_t
JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, CompilerType *base_type_ptr)
{
    return false;
}

bool
JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type)
{
    return static_cast<JavaType *>(type)->IsCompleteType();
}

bool
JavaASTContext::IsConst(lldb::opaque_compiler_type_t type)
{
    return false;
}

bool
JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type)
{
    return false;
}

bool
JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type)
{
    return type != nullptr;
}

bool
JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type)
{
    if (IsCompleteType(type))
        return true;

    if (JavaArrayType *array = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type)))
        return GetCompleteType(array->GetElementType().GetOpaqueQualType());

    if (JavaReferenceType *reference = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
        return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType());

    if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        SymbolFile *symbol_file = GetSymbolFile();
        if (!symbol_file)
            return false;

        CompilerType object_type(this, type);
        return symbol_file->CompleteType(object_type);
    }
    return false;
}

ConstString
JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type)
{
    if (type)
        return static_cast<JavaType *>(type)->GetName();
    return ConstString();
}

uint32_t
JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type, CompilerType *pointee_or_element_compiler_type)
{
    if (pointee_or_element_compiler_type)
        pointee_or_element_compiler_type->Clear();
    if (!type)
        return 0;

    if (IsReferenceType(type, pointee_or_element_compiler_type))
        return eTypeHasChildren | eTypeHasValue | eTypeIsReference;
    if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr))
        return eTypeHasChildren | eTypeIsArray;
    if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
        return eTypeHasChildren | eTypeIsClass;

    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
            case JavaPrimitiveType::eTypeShort:
            case JavaPrimitiveType::eTypeInt:
            case JavaPrimitiveType::eTypeLong:
                return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger | eTypeIsSigned;
            case JavaPrimitiveType::eTypeFloat:
            case JavaPrimitiveType::eTypeDouble:
                return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat | eTypeIsSigned;
            case JavaPrimitiveType::eTypeBoolean:
                return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
            case JavaPrimitiveType::eTypeChar:
                return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
        }
    }
    return 0;
}

lldb::TypeClass
JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type)
{
    if (!type)
        return eTypeClassInvalid;
    if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)))
        return eTypeClassReference;
    if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type)))
        return eTypeClassArray;
    if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
        return eTypeClassClass;
    if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)))
        return eTypeClassBuiltin;
    assert(false && "Java type with unhandled type class");
    return eTypeClassInvalid;
}

lldb::LanguageType
JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type)
{
    return lldb::eLanguageTypeJava;
}

CompilerType
JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride)
{
    if (stride)
        *stride = 0;

    CompilerType element_type;
    if (IsArrayType(type, &element_type, nullptr, nullptr))
        return element_type;
    return CompilerType();
}

CompilerType
JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type)
{
    CompilerType pointee_type;
    if (IsPointerType(type, &pointee_type))
        return pointee_type;
    return CompilerType();
}

CompilerType
JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type)
{
    return CompilerType(); // No pointer types in java
}

CompilerType
JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type)
{
    return CompilerType(this, type);
}

CompilerType
JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type)
{
    return CompilerType(this, type);
}

CompilerType
JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type)
{
    CompilerType pointee_type;
    if (IsReferenceType(type, &pointee_type))
        return pointee_type;
    return CompilerType(this, type);
}

CompilerType
JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type)
{
    return CompilerType();
}

CompilerType
JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type)
{
    return CompilerType();
}

CompilerType
JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, size_t bit_size)
{
    return CompilerType();
}

size_t
JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type)
{
    return 0;
}

lldb::BasicType
JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type)
{
    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
                return eBasicTypeOther;
            case JavaPrimitiveType::eTypeShort:
                return eBasicTypeShort;
            case JavaPrimitiveType::eTypeInt:
                return eBasicTypeInt;
            case JavaPrimitiveType::eTypeLong:
                return eBasicTypeLong;
            case JavaPrimitiveType::eTypeFloat:
                return eBasicTypeFloat;
            case JavaPrimitiveType::eTypeDouble:
                return eBasicTypeDouble;
            case JavaPrimitiveType::eTypeBoolean:
                return eBasicTypeBool;
            case JavaPrimitiveType::eTypeChar:
                return eBasicTypeChar;
        }
    }
    return eBasicTypeInvalid;
}

uint64_t
JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type, ExecutionContextScope *exe_scope)
{
    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
                return 8;
            case JavaPrimitiveType::eTypeShort:
                return 16;
            case JavaPrimitiveType::eTypeInt:
                return 32;
            case JavaPrimitiveType::eTypeLong:
                return 64;
            case JavaPrimitiveType::eTypeFloat:
                return 32;
            case JavaPrimitiveType::eTypeDouble:
                return 64;
            case JavaPrimitiveType::eTypeBoolean:
                return 1;
            case JavaPrimitiveType::eTypeChar:
                return 16;
        }
    }
    else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)))
    {
        return 32; // References are always 4 byte long in java
    }
    else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type)))
    {
        return 64;
    }
    else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        return obj->GetByteSize() * 8;
    }
    return 0;
}

lldb::Encoding
JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type, uint64_t &count)
{
    count = 1;

    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
            case JavaPrimitiveType::eTypeShort:
            case JavaPrimitiveType::eTypeInt:
            case JavaPrimitiveType::eTypeLong:
                return eEncodingSint;
            case JavaPrimitiveType::eTypeFloat:
            case JavaPrimitiveType::eTypeDouble:
                return eEncodingIEEE754;
            case JavaPrimitiveType::eTypeBoolean:
            case JavaPrimitiveType::eTypeChar:
                return eEncodingUint;
        }
    }
    if (IsReferenceType(type))
        return eEncodingUint;
    return eEncodingInvalid;
}

lldb::Format
JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type)
{
    if (JavaPrimitiveType *ptype = llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
    {
        switch (ptype->GetTypeKind())
        {
            case JavaPrimitiveType::eTypeByte:
            case JavaPrimitiveType::eTypeShort:
            case JavaPrimitiveType::eTypeInt:
            case JavaPrimitiveType::eTypeLong:
                return eFormatDecimal;
            case JavaPrimitiveType::eTypeFloat:
            case JavaPrimitiveType::eTypeDouble:
                return eFormatFloat;
            case JavaPrimitiveType::eTypeBoolean:
                return eFormatBoolean;
            case JavaPrimitiveType::eTypeChar:
                return eFormatUnicode16;
        }
    }
    if (IsReferenceType(type))
        return eFormatHex;
    return eFormatDefault;
}

unsigned
JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type)
{
    return 0;
}

size_t
JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type, const char *s, uint8_t *dst,
                                          size_t dst_size)
{
    assert(false && "Not implemented");
    return 0;
}

size_t
JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type)
{
    return 0;
}

CompilerType
JavaASTContext::GetTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, lldb::TemplateArgumentKind &kind)
{
    return CompilerType();
}

uint32_t
JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);
        return obj->GetNumFields();
    }
    return 0;
}

CompilerType
JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx, std::string &name,
                                uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr)
{
    if (bit_offset_ptr)
        *bit_offset_ptr = 0;
    if (bitfield_bit_size_ptr)
        *bitfield_bit_size_ptr = 0;
    if (is_bitfield_ptr)
        *is_bitfield_ptr = false;

    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);

        JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
        if (!field)
            return CompilerType();
        name = field->m_name.AsCString();
        if (bit_offset_ptr)
            *bit_offset_ptr = field->m_offset * 8;
        return field->m_type;
    }
    return CompilerType();
}

uint32_t
JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type, bool omit_empty_base_classes)
{
    GetCompleteType(type);

    if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
        return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes);

    if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
        return GetNumFields(type) + GetNumDirectBaseClasses(type);

    return 0;
}

uint32_t
JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);
        return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0);
    }
    return 0;
}

uint32_t
JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);
        return obj->GetNumInterfaces();
    }
    return 0;
}

CompilerType
JavaASTContext::GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);

        if (CompilerType base_class = obj->GetBaseClass())
        {
            if (idx == 0)
                return base_class;
            else
                --idx;
        }
        return obj->GetInterfaceAtIndex(idx);
    }
    return CompilerType();
}

CompilerType
JavaASTContext::GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);
        return obj->GetInterfaceAtIndex(idx);
    }
    return CompilerType();
}

void
JavaASTContext::DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s, lldb::Format format,
                          const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size,
                          uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types, bool show_summary,
                          bool verbose, uint32_t depth)
{
    assert(false && "Not implemented");
}

bool
JavaASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
                              const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size,
                              uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
                              ExecutionContextScope *exe_scope)
{
    if (IsScalarType(type))
    {
        return data.Dump(s, data_offset, format, data_byte_size,
                         1, // count
                         UINT32_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size, bitfield_bit_offset, exe_scope);
    }
    return false;
}

void
JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type)
{
    StreamFile s(stdout, false);
    DumpTypeDescription(type, &s);
}

void
JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type, Stream *s)
{
    static_cast<JavaType *>(type)->Dump(s);
}

void
JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
                            const DataExtractor &data, lldb::offset_t data_offset, size_t data_byte_size)
{
    assert(false && "Not implemented");
}

int
JavaASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type)
{
    return 0;
}

CompilerType
JavaASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, size_t idx)
{
    return CompilerType();
}

CompilerType
JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type)
{
    return CompilerType();
}

size_t
JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type)
{
    return 0;
}

TypeMemberFunctionImpl
JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx)
{
    return TypeMemberFunctionImpl();
}

CompilerType
JavaASTContext::GetChildCompilerTypeAtIndex(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
                                            bool transparent_pointers, bool omit_empty_base_classes,
                                            bool ignore_array_bounds, std::string &child_name,
                                            uint32_t &child_byte_size, int32_t &child_byte_offset,
                                            uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
                                            bool &child_is_base_class, bool &child_is_deref_of_parent,
                                            ValueObject *valobj, uint64_t &language_flags)
{
    child_name.clear();
    child_byte_size = 0;
    child_byte_offset = 0;
    child_bitfield_bit_size = 0;
    child_bitfield_bit_offset = 0;
    child_is_base_class = false;
    child_is_deref_of_parent = false;
    language_flags = 0;

    ExecutionContextScope *exec_ctx_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;

    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);

        if (CompilerType base_class = obj->GetBaseClass())
        {
            if (idx == 0)
            {
                JavaType *base_class_type = static_cast<JavaType *>(base_class.GetOpaqueQualType());
                child_name = base_class_type->GetName().GetCString();
                child_byte_size = base_class.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
                child_byte_offset = obj->GetBaseClassOffset();
                child_is_base_class = true;
                return base_class;
            }
            idx -= 1;
        }

        JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
        if (!field)
            return CompilerType();

        child_name = field->m_name.AsCString();
        child_byte_size = field->m_type.GetByteSize(exec_ctx_scope);
        child_byte_offset = field->m_offset;
        return field->m_type;
    }
    else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
    {
        CompilerType pointee_type = ref->GetPointeeType();

        if (transparent_pointers)
            return pointee_type.GetChildCompilerTypeAtIndex(
                exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name,
                child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
                child_is_base_class, child_is_deref_of_parent, valobj, language_flags);

        if (idx != 0)
            return CompilerType();

        if (valobj && valobj->GetName())
            child_name = valobj->GetName().GetCString();
        child_is_deref_of_parent = true;
        child_byte_offset = 0;
        child_byte_size = pointee_type.GetByteSize(exec_ctx_scope);
        return pointee_type;
    }
    return CompilerType();
}

uint32_t
JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, const char *name,
                                        bool omit_empty_base_classes)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);

        uint32_t index_offset = 0;
        if (CompilerType base_class = obj->GetBaseClass())
        {
            if (base_class.GetTypeName() == ConstString(name))
                return 0;
            index_offset = 1;
        }
        for (uint32_t i = 0; i < obj->GetNumFields(); ++i)
        {
            if (obj->GetFieldAtIndex(i)->m_name == ConstString(name))
                return i + index_offset;
        }
    }
    else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
    {
        return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes);
    }
    return UINT_MAX;
}

size_t
JavaASTContext::GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, const char *name,
                                              bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes)
{
    child_indexes.clear();

    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type)))
    {
        GetCompleteType(type);

        uint32_t index_offset = 0;
        if (CompilerType base_class = obj->GetBaseClass())
        {
            if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name, omit_empty_base_classes,
                                              child_indexes) != 0)
            {
                child_indexes.insert(child_indexes.begin(), 0);
                return child_indexes.size();
            }
            index_offset = 1;
        }

        for (uint32_t i = 0; i < obj->GetNumFields(); ++i)
        {
            if (obj->GetFieldAtIndex(i)->m_name == ConstString(name))
            {
                child_indexes.push_back(i + index_offset);
                return child_indexes.size();
            }
        }
    }
    else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
    {
        return GetIndexOfChildMemberWithName(ref->GetPointeeType().GetOpaqueQualType(), name, omit_empty_base_classes,
                                             child_indexes);
    }
    return 0;
}

CompilerType
JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type)
{
    return CreateReferenceType(CompilerType(this, type));
}

ConstString
JavaASTContext::DeclContextGetScopeQualifiedName(lldb::opaque_compiler_type_t opaque_decl_ctx)
{
    return GetTypeName(opaque_decl_ctx);
}

static void
AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map, JavaPrimitiveType::TypeKind type_kind)
{
    JavaPrimitiveType *type = new JavaPrimitiveType(type_kind);
    type_map.emplace(type->GetName(), std::unique_ptr<JavaASTContext::JavaType>(type));
}

CompilerType
JavaASTContext::CreateBaseType(const ConstString &name)
{
    if (m_base_type_map.empty())
    {
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean);
        AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar);
    }
    auto it = m_base_type_map.find(name);
    if (it != m_base_type_map.end())
        return CompilerType(this, it->second.get());
    return CompilerType();
}

CompilerType
JavaASTContext::CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size)
{
    auto it = m_object_type_map.find(name);
    if (it == m_object_type_map.end())
    {
        std::unique_ptr<JavaType> object_type(new JavaObjectType(name, linkage_name, byte_size));
        it = m_object_type_map.emplace(name, std::move(object_type)).first;
    }
    return CompilerType(this, it->second.get());
}

CompilerType
JavaASTContext::CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type,
                                const DWARFExpression &length_expression, const lldb::addr_t data_offset)
{
    ConstString name = element_type.GetTypeName();
    auto it = m_array_type_map.find(name);
    if (it == m_array_type_map.end())
    {
        std::unique_ptr<JavaType> array_type(new JavaArrayType(linkage_name, element_type, length_expression,
                                                               data_offset));
        it = m_array_type_map.emplace(name, std::move(array_type)).first;
    }
    return CompilerType(this, it->second.get());
}

CompilerType
JavaASTContext::CreateReferenceType(const CompilerType &pointee_type)
{
    ConstString name = pointee_type.GetTypeName();
    auto it = m_reference_type_map.find(name);
    if (it == m_reference_type_map.end())
        it = m_reference_type_map.emplace(name, std::unique_ptr<JavaType>(new JavaReferenceType(pointee_type))).first;
    return CompilerType(this, it->second.get());
}

void
JavaASTContext::CompleteObjectType(const CompilerType &object_type)
{
    JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType()));
    assert(obj && "JavaASTContext::CompleteObjectType called with not a JavaObjectType");
    obj->SetCompleteType(true);
}

void
JavaASTContext::AddBaseClassToObject(const CompilerType &object_type, const CompilerType &member_type,
                                     uint32_t member_offset)
{
    JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType()));
    assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType");
    obj->AddBaseClass(member_type, member_offset);
}

void
JavaASTContext::AddMemberToObject(const CompilerType &object_type, const ConstString &name,
                                  const CompilerType &member_type, uint32_t member_offset)
{
    JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(object_type.GetOpaqueQualType()));
    assert(obj && "JavaASTContext::AddMemberToObject called with not a JavaObjectType");
    obj->AddField(name, member_type, member_offset);
}

void
JavaASTContext::SetDynamicTypeId(const CompilerType &type, const DWARFExpression &type_id)
{
    JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType()));
    assert(obj && "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType");
    obj->SetDynamicTypeId(type_id);
}

uint64_t
JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx, const CompilerType &type, ValueObject &in_value)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
        return obj->CalculateDynamicTypeId(exe_ctx, in_value);
    if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
        return arr->CalculateDynamicTypeId(exe_ctx, in_value);
    return UINT64_MAX;
}

uint32_t
JavaASTContext::CalculateArraySize(const CompilerType &type, ValueObject &in_value)
{
    if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
        return arr->GetNumElements(&in_value);
    return UINT32_MAX;
}

uint64_t
JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, size_t index)
{
    if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
        return arr->GetElementOffset(index);
    return UINT64_MAX;
}

ConstString
JavaASTContext::GetLinkageName(const CompilerType &type)
{
    if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type.GetOpaqueQualType())))
        return obj->GetLinkageName();
    return ConstString();
}
