/*
    Copyright (c) 2007 SIEGE Development Team
    All rights reserved.
    
    This file is part of libSIEGE.
    
    This software is copyrighted work licensed under the terms of the
    2-clause BSD license. Please consult the file "license.txt" for
    details.
    
    If you did not recieve the file with this program, please email
    Tim Chas <darkuranium@gmail.com>.
*/

#include "entity.h"

SGvoid SG_EXPORT evInit(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evInit", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evDeinit(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evDeinit", NULL);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evStart(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evStart", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evExit(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evExit", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evTick(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evTick", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evTickBegin(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evTickBegin", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evTickEnd(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evTickEnd", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evDraw(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evDraw", NULL);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evWindowOpen(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evWindowOpen", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evWindowClose(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evWindowClose", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evWindowResize(SGEntity* entity, SGuint width, SGuint height)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evWindowResize", "II", width, height);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evMouseButton(SGEntity* entity, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButton", "I", button);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonPress(SGEntity* entity, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonPress", "I", button);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonRelease(SGEntity* entity, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonRelease", "I", button);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evMouseButtonLeft(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonLeft", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonLeftPress(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonLeftPress", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonLeftRelease(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonLeftRelease", NULL);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evMouseButtonRight(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonRight", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonRightPress(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonRightPress", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonRightRelease(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonRightRelease", NULL);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evMouseButtonMiddle(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonMiddle", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonMiddlePress(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonMiddlePress", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseButtonMiddleRelease(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseButtonMiddleRelease", NULL);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evMouseMove(SGEntity* entity, SGint x, SGint y)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseMove", "ii", x, y);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evMouseWheel(SGEntity* entity, SGint wheel)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evMouseWheel", "i", wheel);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evKeyboardKey(SGEntity* entity, SGuint key)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardKey", "I", key);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evKeyboardKeyPress(SGEntity* entity, SGuint key)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardKeyPress", "I", key);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evKeyboardKeyRelease(SGEntity* entity, SGuint key)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardKeyRelease", "I", key);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evKeyboardKeyRepeat(SGEntity* entity, SGuint key)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardKeyRepeat", "I", key);
    Py_DECREF(ret);
}

/*SGvoid SG_EXPORT evKeyboardChar(SGEntity* entity, SGdchar chr)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardChar", "I", chr);
    Py_DECREF(ret);
}*/
SGvoid SG_EXPORT evKeyboardCharPress(SGEntity* entity, SGdchar chr)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardCharPress", "I", chr);
    Py_DECREF(ret);
}
/*SGvoid SG_EXPORT evKeyboardCharRelease(SGEntity* entity, SGdchar chr)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardCharRelease", "I", chr);
    Py_DECREF(ret);
}*/
SGvoid SG_EXPORT evKeyboardCharRepeat(SGEntity* entity, SGdchar chr)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evKeyboardCharRepeat", "I", chr);
    Py_DECREF(ret);
}

SGvoid SG_EXPORT evJoystickButton(SGEntity* entity, SGuint joy, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evJoystickButton", "II", joy, button);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evJoystickButtonPress(SGEntity* entity, SGuint joy, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evJoystickButtonPress", "II", joy, button);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evJoystickButtonRelease(SGEntity* entity, SGuint joy, SGuint button)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evJoystickButtonRelease", "II", joy, button);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evJoystickMove(SGEntity* entity, SGuint joy, SGfloat* axis, SGuint numaxis)
{
    PyObject* list = PyList_New(numaxis);
    SGuint i;
    for(i = 0; i < numaxis; i++)
    {
        PyObject* val = Py_BuildValue("f", axis[i]);
        PyList_SET_ITEM(list, i, val);
        Py_DECREF(val);
    }

    PyObject* ret = PyObject_CallMethod(entity->data, "evJoystickButtonRelease", "IN", joy, list);
    Py_DECREF(ret);
}

// networking goes here

SGvoid SG_EXPORT evCollision(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionOne(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionTwo(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);

SGvoid SG_EXPORT evCollisionBegin(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionOneBegin(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionTwoBegin(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);

SGvoid SG_EXPORT evCollisionEnd(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionOneEnd(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);
SGvoid SG_EXPORT evCollisionTwoEnd(SGEntity* entity, SGEntity* other, SGCollisionPoint* point);

SGvoid SG_EXPORT evCollisionResult(SGEntity* entity, SGEntity* other, SGCollisionResult* result);
SGvoid SG_EXPORT evCollisionOneResult(SGEntity* entity, SGEntity* other, SGCollisionResult* result);
SGvoid SG_EXPORT evCollisionTwoResult(SGEntity* entity, SGEntity* other, SGCollisionResult* result);

SGvoid SG_EXPORT evLevelStart(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evLevelStart", NULL);
    Py_DECREF(ret);
}
SGvoid SG_EXPORT evLevelEnd(SGEntity* entity)
{
    PyObject* ret = PyObject_CallMethod(entity->data, "evLevelEnd", NULL);
    Py_DECREF(ret);
}

static void pysEntityDealloc(PysEntity* self)
{
    Py_XDECREF(self->sprite);
    Py_XDECREF(self->mask);
    Py_XDECREF(self->body);
    Py_XDECREF(self->source);

    sgEntityDestroy(self->entity);
    self->ob_type->tp_free(self);
}
static PyObject* pysEntityNew(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
    PysEntity* self = (PysEntity*)type->tp_alloc(type, 0);
    if(self != NULL)
    {
        self->sprite = NULL;
        self->mask = NULL;
        self->body = NULL;
        self->source = NULL;

        self->entity = NULL;
    }
    return (PyObject*)self;
}
static int pysEntityInit(PysEntity* self, PyObject* args, PyObject* kwargs)
{
    float priority;
    SGenum type;
    if(!PyArg_ParseTuple(args, "fI", &priority, &type))
        return -1;

    self->entity = sgEntityCreate(priority, type);
    self->entity->data = self;

    self->entity->evInit = evInit;
    self->entity->evDeinit = evDeinit;

    self->entity->evStart = evStart;
    self->entity->evExit = evExit;
    self->entity->evTick = evTick;
    self->entity->evTickBegin = evTickBegin;
    self->entity->evTickEnd = evTickEnd;
    self->entity->evDraw = evDraw;

    self->entity->evWindowOpen = evWindowOpen;
    self->entity->evWindowClose = evWindowClose;
    self->entity->evWindowResize = evWindowResize;

    self->entity->evMouseButton = evMouseButton;
    self->entity->evMouseButtonPress = evMouseButtonPress;
    self->entity->evMouseButtonRelease = evMouseButtonRelease;

    self->entity->evMouseButtonLeft = evMouseButtonLeft;
    self->entity->evMouseButtonLeftPress = evMouseButtonLeftPress;
    self->entity->evMouseButtonLeftRelease = evMouseButtonLeftRelease;

    self->entity->evMouseButtonRight = evMouseButtonRight;
    self->entity->evMouseButtonRightPress = evMouseButtonRightPress;
    self->entity->evMouseButtonRightRelease = evMouseButtonRightRelease;

    self->entity->evMouseButtonMiddle = evMouseButtonMiddle;
    self->entity->evMouseButtonMiddlePress = evMouseButtonMiddlePress;
    self->entity->evMouseButtonMiddleRelease = evMouseButtonMiddleRelease;

    self->entity->evMouseMove = evMouseMove;
    self->entity->evMouseWheel = evMouseWheel;

    self->entity->evKeyboardKey = evKeyboardKey;
    self->entity->evKeyboardKeyPress = evKeyboardKeyPress;
    self->entity->evKeyboardKeyRelease = evKeyboardKeyRelease;
    self->entity->evKeyboardKeyRepeat = evKeyboardKeyRepeat;

    //self->entity->evKeyboardChar = evKeyboardChar;
    self->entity->evKeyboardCharPress = evKeyboardCharPress;
    //self->entity->evKeyboardCharRelease = evKeyboardCharRelease;
    self->entity->evKeyboardCharRepeat = evKeyboardCharRepeat;

    self->entity->evJoystickButton = evJoystickButton;
    self->entity->evJoystickButtonPress = evJoystickButtonPress;
    self->entity->evJoystickButtonRelease = evJoystickButtonRelease;
    self->entity->evJoystickMove = evJoystickMove;

    // networking goes here

    /*self->entity->evCollision = evCollision;
    self->entity->evCollisionOne = evCollisionOne;
    self->entity->evCollisionTwo = evCollisionTwo;

    self->entity->evCollisionBegin = evCollisionBegin;
    self->entity->evCollisionOneBegin = evCollisionOneBegin;
    self->entity->evCollisionTwoBegin = evCollisionTwoBegin;

    self->entity->evCollisionEnd = evCollisionEnd;
    self->entity->evCollisionOneEnd = evCollisionOneEnd;
    self->entity->evCollisionTwoEnd = evCollisionTwoEnd;

    self->entity->evCollisionResult = evCollisionResult;
    self->entity->evCollisionOneResult = evCollisionOneResult;
    self->entity->evCollisionTwoResult = evCollisionTwoResult;*/

    self->entity->evLevelStart = evLevelStart;
    self->entity->evLevelEnd = evLevelEnd;

    return 0;
}

static PyObject* pysEntitySetSprite(PysEntity* self, PyObject* args)
{
    PysSprite* sprite;
    PyArg_ParseTuple(args, "O", &sprite);

    Py_INCREF(self->sprite);
    self->sprite = sprite;
    sgEntitySetSprite(self->entity, sprite->sprite);

    Py_RETURN_NONE;
}
static PysSprite* pysEntityGetSprite(PysEntity* self)
{
    Py_INCREF(self->sprite);
    return self->sprite;
}

static PyObject* pysEntitySetMask(PysEntity* self, PyObject* args)
{
    PysSprite* mask;
    PyArg_ParseTuple(args, "O", &mask);

    Py_INCREF(self->mask);
    self->mask = mask;
    sgEntitySetMask(self->entity, mask->sprite);

    Py_RETURN_NONE;
}
static PysSprite* pysEntityGetMask(PysEntity* self)
{
    Py_INCREF(self->mask);
    return self->mask;
}

static PyObject* pysEntitySetPhysicsBody(PysEntity* self, PyObject* args)
{
    PysPhysicsBody* body;
    PyArg_ParseTuple(args, "O", &body);

    Py_INCREF(self->body);
    self->body = body;
    sgEntitySetPhysicsBody(self->entity, body->body);

    Py_RETURN_NONE;
}
static PysPhysicsBody* pysEntityGetPhysicsBody(PysEntity* self)
{
    Py_INCREF(self->body);
    return self->body;
}

static PyObject* pysEntitySetAudioSource(PysEntity* self, PyObject* args)
{
    PysSource* source;
    PyArg_ParseTuple(args, "O", &source);

    Py_INCREF(self->source);
    self->source = source;
    sgEntitySetAudioSource(self->entity, source->source);

    Py_RETURN_NONE;
}
static PysSource* pysEntityGetAudioSource(PysEntity* self)
{
    Py_INCREF(self->source);
    return self->source;
}

static PyObject* pysEntitySetPos(PysEntity* self, PyObject* args)
{
    float x, y;
    PyArg_ParseTuple(args, "ff", &x, &y);

    sgEntitySetPos(self->entity, x, y);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetPos(PysEntity* self)
{
    float x, y;
    sgEntityGetPos(self->entity, &x, &y);

    return Py_BuildValue("(ff)", x, y);
}
static PyObject* pysEntitySetPosX(PysEntity* self, PyObject* args)
{
    float x;
    PyArg_ParseTuple(args, "f", &x);

    sgEntitySetPosX(self->entity, x);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetPosX(PysEntity* self)
{
    return Py_BuildValue("f", sgEntityGetPosX(self->entity));
}
static PyObject* pysEntitySetPosY(PysEntity* self, PyObject* args)
{
    float y;
    PyArg_ParseTuple(args, "f", &y);

    sgEntitySetPosY(self->entity, y);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetPosY(PysEntity* self)
{
    return Py_BuildValue("f", sgEntityGetPosY(self->entity));
}

static PyObject* pysEntitySetDepth(PysEntity* self, PyObject* args)
{
    float depth;
    PyArg_ParseTuple(args, "f", &depth);

    sgEntitySetDepth(self->entity, depth);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetDepth(PysEntity* self)
{
    return Py_BuildValue("f", sgEntityGetDepth(self->entity));
}

static PyObject* pysEntitySetAngleRads(PysEntity* self, PyObject* args)
{
    float rads;
    PyArg_ParseTuple(args, "f", &rads);

    sgEntitySetAngleRads(self->entity, rads);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetAngleRads(PysEntity* self)
{
    return Py_BuildValue("f", sgEntityGetAngleRads(self->entity));
}

static PyObject* pysEntitySetAngleDegs(PysEntity* self, PyObject* args)
{
    float degs;
    PyArg_ParseTuple(args, "f", &degs);

    sgEntitySetAngleDegs(self->entity, degs);

    Py_RETURN_NONE;
}
static PyObject* pysEntityGetAngleDegs(PysEntity* self)
{
    return Py_BuildValue("f", sgEntityGetAngleDegs(self->entity));
}

static PyObject* pysEntityDraw(PysEntity* self)
{
    sgEntityDraw(self->entity);
    Py_RETURN_NONE;
}

static PyMethodDef PysEntityMethods[] = {
    {"setSprite", (PyCFunction)pysEntitySetSprite, METH_VARARGS, ""},
    {"getSprite", (PyCFunction)pysEntityGetSprite, METH_NOARGS, ""},

    {"setMask", (PyCFunction)pysEntitySetMask, METH_VARARGS, ""},
    {"getMask", (PyCFunction)pysEntityGetMask, METH_NOARGS, ""},

    {"setPhysicsBody", (PyCFunction)pysEntitySetPhysicsBody, METH_VARARGS, ""},
    {"getPhysicsBody", (PyCFunction)pysEntityGetPhysicsBody, METH_NOARGS, ""},

    {"setAudioSource", (PyCFunction)pysEntitySetAudioSource, METH_VARARGS, ""},
    {"getAudioSource", (PyCFunction)pysEntityGetAudioSource, METH_NOARGS, ""},

    {"setPos", (PyCFunction)pysEntitySetPos, METH_VARARGS, ""},
    {"getPos", (PyCFunction)pysEntityGetPos, METH_NOARGS, ""},
    {"setPosX", (PyCFunction)pysEntitySetPosX, METH_VARARGS, ""},
    {"getPosX", (PyCFunction)pysEntityGetPosX, METH_NOARGS, ""},
    {"setPosY", (PyCFunction)pysEntitySetPosY, METH_VARARGS, ""},
    {"getPosY", (PyCFunction)pysEntityGetPosY, METH_NOARGS, ""},

    {"setDepth", (PyCFunction)pysEntitySetDepth, METH_VARARGS, ""},
    {"getDepth", (PyCFunction)pysEntityGetDepth, METH_NOARGS, ""},

    {"setAngleRads", (PyCFunction)pysEntitySetAngleRads, METH_VARARGS, ""},
    {"getAngleRads", (PyCFunction)pysEntityGetAngleRads, METH_NOARGS, ""},

    {"setAngleDegs", (PyCFunction)pysEntitySetAngleDegs, METH_VARARGS, ""},
    {"getAngleDegs", (PyCFunction)pysEntityGetAngleDegs, METH_NOARGS, ""},

    {"draw", (PyCFunction)pysEntityDraw, METH_NOARGS, ""},
    {NULL, NULL, 0, NULL}
};
static PyMemberDef PysEntityMembers[] = {
    {NULL, 0, 0, 0, NULL}
};

static PyTypeObject PysEntityType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "siege.core.Entity",   /*tp_name*/
    sizeof(PysEntity),         /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)pysEntityDealloc, /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
    "",                        /* tp_doc */
    0,		                   /* tp_traverse */
    0,		                   /* tp_clear */
    0,		                   /* tp_richcompare */
    0,		                   /* tp_weaklistoffset */
    0,		                   /* tp_iter */
    0,		                   /* tp_iternext */
    PysEntityMethods,          /* tp_methods */
    PysEntityMembers,          /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)pysEntityInit,   /* tp_init */
    0,                         /* tp_alloc */
    pysEntityNew,                 /* tp_new */
};

int pysEntityCheck(PyObject* o)
{
    return PyObject_TypeCheck(o, &PysEntityType);
}
void sgpyInitCoreEntity(PyObject* parent)
{
    PysEntityType.tp_new = PyType_GenericNew;
    if(PyType_Ready(&PysEntityType) < 0)
        return;

    Py_INCREF(&PysEntityType);
    PyModule_AddObject(parent, "Entity", (PyObject*)&PysEntityType);
}
