/*
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

#include <jni.h>
#include "JCCEnv.h"
#include "java/lang/Class.h"
#include "java/lang/Object.h"
#include "java/lang/String.h"
#include "java/lang/reflect/Field.h"
#ifdef _java_generics
#include "java/lang/reflect/Type.h"
#endif

namespace java {
    namespace lang {
        namespace reflect {

            enum {
                mid_getModifiers,
                mid_getType,
                mid_getName,
#ifdef _java_generics
                mid_getGenericType,
#endif
                max_mid
            };

            Class *Field::class$ = NULL;
            jmethodID *Field::_mids = NULL;

            jclass Field::initializeClass(bool getOnly)
            {
                if (getOnly)
                    return (jclass) (class$ == NULL ? NULL : class$->this$);
                if (!class$)
                {
                    jclass cls = env->findClass("java/lang/reflect/Field");

                    _mids = new jmethodID[max_mid];
                    _mids[mid_getModifiers] =
                        env->getMethodID(cls, "getModifiers",
                                         "()I");
                    _mids[mid_getType] =
                        env->getMethodID(cls, "getType",
                                         "()Ljava/lang/Class;");
                    _mids[mid_getName] =
                        env->getMethodID(cls, "getName",
                                         "()Ljava/lang/String;");
#ifdef _java_generics
                    _mids[mid_getGenericType] =
                        env->getMethodID(cls, "getGenericType",
                                         "()Ljava/lang/reflect/Type;");
#endif

                    class$ = (Class *) new JObject(cls);
                }

                return (jclass) class$->this$;
            }

            int Field::getModifiers() const
            {
                return env->callIntMethod(this$, _mids[mid_getModifiers]);
            }

            Class Field::getType() const
            {
                return Class(env->callObjectMethod(this$, _mids[mid_getType]));
            }

            String Field::getName() const
            {
                return String(env->callObjectMethod(this$, _mids[mid_getName]));
            }

#ifdef _java_generics
            Type Field::getGenericType() const
            {
                return Type(env->callObjectMethod(this$, _mids[mid_getGenericType]));
            }
#endif
        }
    }
}


#include "structmember.h"
#include "functions.h"
#include "macros.h"

namespace java {
    namespace lang {
        namespace reflect {

            static PyObject *t_Field_getModifiers(t_Field *self);
            static PyObject *t_Field_getType(t_Field *self);
            static PyObject *t_Field_getName(t_Field *self);
#ifdef _java_generics
            static PyObject *t_Field_getGenericType(t_Field *self);
#endif

            static PyMethodDef t_Field__methods_[] = {
                DECLARE_METHOD(t_Field, getModifiers, METH_NOARGS),
                DECLARE_METHOD(t_Field, getType, METH_NOARGS),
                DECLARE_METHOD(t_Field, getName, METH_NOARGS),
#ifdef _java_generics
                DECLARE_METHOD(t_Field, getGenericType, METH_NOARGS),
#endif
                { NULL, NULL, 0, NULL }
            };

            static PyType_Slot PY_TYPE_SLOTS(Field)[] = {
                { Py_tp_methods, t_Field__methods_ },
                { Py_tp_init, (void *) abstract_init },
                { 0, 0 }
            };

            static PyType_Def *PY_TYPE_BASES(Field)[] = {
                &PY_TYPE_DEF(Object),
                NULL
            };

            DEFINE_TYPE(Field, t_Field, Field);

            static PyObject *t_Field_getModifiers(t_Field *self)
            {
                jint modifiers;

                OBJ_CALL(modifiers = self->object.getModifiers());
                return PyLong_FromLong(modifiers);
            }

            static PyObject *t_Field_getType(t_Field *self)
            {
                Class cls((jobject) NULL);

                OBJ_CALL(cls = self->object.getType());
                return t_Class::wrap_Object(cls);
            }

            static PyObject *t_Field_getName(t_Field *self)
            {
                String name((jobject) NULL);

                OBJ_CALL(name = self->object.getName());
                return j2p(name);
            }

#ifdef _java_generics
            static PyObject *t_Field_getGenericType(t_Field *self)
            {
                Type result((jobject) NULL);
                OBJ_CALL(result = self->object.getGenericType());

                return t_Type::wrap_Object(result);
            }
#endif
        }
    }
}
