// CustomAttribute.h

#ifndef _CustomAttribute_H_
#define _CustomAttribute_H_

#include "Object.h"

class String;
class TypeInfo;
class ByteBuffer;
class MemberRef;
class NamedArg;
class Type;

/**
Decompile a custom attribute
*/
// public 
class CustomAttribute : public Object
{
    
protected: 
    /**
    The raw methodref token
    */
    int methodRefToken;

    /**
    The constructor to form this attribute
    */
    MemberRef* constructor;

    Array<Object*>* args;

    Array<NamedArg*>* namedArgs;

    /**
    Attribute could attach to type, method, field, property, event,
    delegate, method parameter, etc., target specifies to which
    object it attaches.
    */
    Object* target;

    
package: 
    /**
    in which type this attribute's target is defined
    */
    TypeInfo* classfile;

    
public:
    CustomAttribute(int mdMethodRef, Array<Object*>* args, Array<NamedArg*>* namedArgs, Object* target);

    
private: 
    static TypeInfo* getTypeInfo(Object* target);

    
public:
    virtual Array<Object*>* getArgs();

    virtual Array<NamedArg*>* getNamedArgs();

    
private: 
    static void emitStringAsILAsm(ByteBuffer* buf, String str);

    /**
    write a constant value according to ILAsm custom attribute blob format
    */
    void writeValueAsILAsm(ByteBuffer* tmp, Type* t, Object* val);

    /**
    Emit type for named arg
    */
    static void emitType(ByteBuffer* buf, Type* t);

    
public:
    virtual void outputAsILAsm(ByteBuffer* buf);

    
private: 
    void writeValue(ByteBuffer* buf, Type* t, Object* val);

    
public:
    /**
    Generate a C# rep, e.g., [MyAttribute("Christina", "Zhang")]
    */
    virtual void output(ByteBuffer* buf, boolean isReturnTarget);

    /**
    Generate a C# rep, e.g., [MyAttribute("Christina", "Zhang")]
    */
    virtual void output(ByteBuffer* buf, String target);

    
private: 
    void output(ByteBuffer* buf);

    
public:
    /**
    Check if this is a System.ParamArrayAttribute
    */
    virtual boolean isParamArrayAttribute();

    /**
    Check if this is a System.ParamArrayAttribute
    */
    virtual boolean isDefaultMemberAttribute();

    /**
    Check if this is a System.Diagnostics.DebuggableAttribute
    */
    virtual boolean isDebuggableAttribute();

    /**
    Get the type that defines this attribute
    */
    virtual Type* getDeclaringType();


protected:
    virtual Object* clone();
};

#endif // _CustomAttribute_H_
