/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.reflection;

/**
 * This enum represents attributes of any IElement (class, field, method, etc)
 *
 * Each enum contains two int bitmasks: first one is used by IAttributes, second one is
 * bitmask used by java reflection API.
 *
 * Most of the time we tried to use identical mask values for both fields.
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
@SuppressWarnings("JavadocReference")
public enum IAttribute {

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#PUBLIC}
     */
    PUBLIC          (0x0000_0001),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#PRIVATE}
     */
    PRIVATE         (0x0000_0002),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#PROTECTED}
     */
    PROTECTED       (0x0000_0004),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#STATIC}
     */
    STATIC          (0x0000_0008),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#FINAL}
     */
    FINAL           (0x0000_0010),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#SYNCHRONIZED}
     */
    SYNCHRONIZED    (0x0000_0020),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#VOLATILE}
     *
     * Warning: java reflection API uses the same value for BRIGDE.
     * This attribute is allowed only for IField
     */
    VOLATILE        (0x0000_0040),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#TRANSIENT}
     *
     * Warning: java reflection API uses the same value for VARARGS.
     * This attribute is allowed only for IField
     */
    TRANSIENT       (0x0000_0080),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#NATIVE}
     */
    NATIVE          (0x0000_0100),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#INTERFACE}
     */
    INTERFACE       (0x0000_0200),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#ABSTRACT}
     */
    ABSTRACT        (0x0000_0400),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#STRICT}
     */
    STRICT          (0x0000_0800),

    /**
     *  This is standard reflective attribute: {@link java.lang.reflect.Modifier#BRIDGE}
     *
     *  Warning: java reflection API uses the same value for VOLATILE.
     *  This attribute is allowed only for IMethod
     */
    BRIDGE          (0x0100_0000, 0x0000_0040),

    /**
     *  This is standard reflective attribute: {@link java.lang.reflect.Modifier#VARARGS}
     *
     *  Warning: java reflection API uses the same value for TRANSIENT.
     *  This attribute is allowed only for IMethod
     */
    VARARGS         (0x0200_0000, 0x0000_0080),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#SYNTHETIC}
     */
    SYNTHETIC       (0x0000_1000),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#ANNOTATION}
     */
    ANNOTATION      (0x0000_2000),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#ENUM}
     */
    ENUM            (0x0000_4000),

    /**
     * This is standard reflective attribute: {@link java.lang.reflect.Modifier#MANDATED}
     */
    MANDATED        (0x0000_8000),

    /**
     * This is non standard attribute: it means that IElement has package scope
     * Allowed for class, methods and fields.
     */
    PACKAGE         (0x0400_0000, 0),   // special: !(public | protected | private)

    /**
     * This non standard attribute: it means that IElement is generic
     * Allowed for class, methods and fields.
     */
    PARAMETERIZED   (0x1000_0000, 0),   // special: is generic class

    /**
     * This is non standard attribute:
     * it means that IElement is declared inside "this" class (not inherited from parent class).
     * 
     * Allowed for inner classes, methods and fields.
     * Used by IHints to filter out inherited members.
     */
    DECLARED        (0x4000_0000, 0),   // special: used in IClass to disable deep scan

    /**
     * This non standard attribute: it means that IMethod is labmda expression
     */
    LAMBDA          (0x8000_0000, 0),

    /**
     * This is non standard attribute:
     * it means that IElement is declared or inherited.
     * 
     * Allowed for inner classes, methods and fields.
     *
     * USAGE:
     * Can be used by IHints and IElements. If marked as required, it enables deep scan
     * which returns both public and non-public members, including inherited ones.
     */
    ANY             (0x0020_0000, 0),

    /**
     * This is type trait: it means that IClass is array
     */
    ARRAY           (0x0001_0000, 0),

    /**
     * This is type trait: it means that IClass is primitive type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isPrimitive 
     */
    PRIMITIVE       (0x0002_0000, 0),

    /**
     * This is type trait: it means that IClass is numerical type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isNumber
     */
    NUMBER          (0x2000_0000, 0),   // special: traits

    /**
     * This is type trait: it means that IClass is integer type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isInteger
     */
    INTEGER         (0x0040_0000, 0),   // special: traits

    /**
     * This is type trait: it means that IClass is boxed type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isBoxed
     */
    BOXED           (0x0004_0000, 0),   // special: traits

    /**
     * This is type trait: it means that IClass is void type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isVoid
     */
    VOID            (0x0008_0000, 0),   // special: traits

    /**
     * This is type trait: it means that IClass is boolean type
     *
     * @see net.ranides.assira.reflection.util.ClassTraits#isBool
     */
    BOOLEAN         (0x0010_0000, 0),   // special: traits

    /**
     * This is non standard attribute:
     * it means that IElement does not represent "real reflective" object,
     * but contains only information about name and signature (more or less)
     *
     * Allowed for classes and methods.
     */
    SYMBOLIC        (0x0800_0000),

    RESOLVED        (0x0080_0000, 0)

    ;

    /**
     * This field is bitmask used by IAttributes container
     */
    final int mask;

    /**
     * This field represents bitmask compatible with {@link java.lang.reflect.Modifier}
     * Obviously returned mask does not contain non-standard attributes.
     */
    final int reflective;

    IAttribute(int mask) {
        this(mask, mask);
    }

    IAttribute(int mask, int reflective) {
        this.mask = mask;
        this.reflective = reflective;
    }

}
