/*
    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 "texture.h"

static void pysTextureDealloc(PysTexture* self)
{
    sgTextureDestroy(self->texture);
    self->ob_type->tp_free(self);
}
static PyObject* pysTextureNew(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
    PysTexture* self = (PysTexture*)type->tp_alloc(type, 0);
    if(self != NULL)
        self->texture = NULL;
    return (PyObject*)self;
}
static int pysTextureInit(PysTexture* self, PyObject* args, PyObject* kwargs)
{
    PyObject* fwidth;
    SGuint height = (SGuint)-1;
    SGenum bpp = (SGuint)-1;
    PyObject* data = NULL;
    if(!PyArg_ParseTuple(args, "O|IIO", &fwidth, &height, &bpp, &data));
        return -1;

    if(data != NULL)
    {
        if(!PyByteArray_Check(data))
            return -1;
        SGuint width = PyInt_AsLong(fwidth);
        if(width == (SGuint)-1) // -1 is an illegal value anyways - no need for PyErr_Occured()
            return -1;

        /// \todo Check data length
        self->texture = sgTextureCreateData(width, height, bpp, PyByteArray_AS_STRING(data));
    }
    else if(bpp != (SGenum)-1)
    {
        SGuint width = PyInt_AsLong(fwidth);
        if(width == (SGuint)-1) // -1 is an illegal value anyways - no need for PyErr_Occured()
            return -1;
        self->texture = sgTextureCreate(width, height, bpp);
    }
    else if(height == (SGuint)-1) // height must not be provided if bpp isn't!
    {
        char* fname = PyString_AsString(fwidth);
        if(fname == NULL)
            return -1;
        self->texture = sgTextureCreateFile(fname);
    }

    return 0;
}

/*
    x,y,z,xscale,yscale,oxffset,yoffset,angle
    x,y,xscale,yscale,xoffset,yoffset,angle
    x,y,z,xscale,yscale,angle
    x,y,xscale,yscale,angle
    x,y,z,angle
    x,y,angle
*/
static PyObject* pysTextureDrawRads(PysTexture* self, PyObject* args)
{
    float x, y, z;
    float xscale, yscale;
    float xoffset, yoffset;
    float rads;

    size_t size = PyTuple_Size(args);
    if(size == 8)
    {
        if(!PyArg_ParseTuple(args, "ffffffff", &x, &y, &z, &xscale, &yscale, &xoffset, &yoffset, &rads))
            return NULL;
        sgTextureDrawRads3f2f2f1f(self->texture, x, y, z, xscale, yscale, xoffset, yoffset, rads);
    }
    else if(size == 7)
    {
        if(!PyArg_ParseTuple(args, "fffffff", &x, &y, &xscale, &yscale, &xoffset, &yoffset, &rads))
            return NULL;
        sgTextureDrawRads2f2f2f1f(self->texture, x, y, xscale, yscale, xoffset, yoffset, rads);
    }
    else if(size == 6)
    {
        if(!PyArg_ParseTuple(args, "ffffff", &x, &y, &z, &xscale, &yscale, &rads))
            return NULL;
        sgTextureDrawRads3f2f1f(self->texture, x, y, z, xscale, yscale, rads);
    }
    else if(size == 5)
    {
        if(!PyArg_ParseTuple(args, "fffff", &x, &y, &xscale, &yscale, &rads))
            return NULL;
        sgTextureDrawRads2f2f1f(self->texture, x, y, xscale, yscale, rads);
    }
    else if(size == 4)
    {
        if(!PyArg_ParseTuple(args, "ffff", &x, &y, &z, &rads))
            return NULL;
        sgTextureDrawRads3f1f(self->texture, x, y, z, rads);
    }
    else if(size == 3)
    {
        if(!PyArg_ParseTuple(args, "fff", &x, &y, &rads))
            return NULL;
        sgTextureDrawRads2f1f(self->texture, x, y, rads);
    }
    else
        return NULL;
    Py_RETURN_NONE;
}

/*
    x,y,z,xscale,yscale,oxffset,yoffset,angle
    x,y,xscale,yscale,xoffset,yoffset,angle
    x,y,z,xscale,yscale,angle
    x,y,xscale,yscale,angle
    x,y,z,angle
    x,y,angle
*/
static PyObject* pysTextureDrawDegs(PysTexture* self, PyObject* args)
{
    float x, y, z;
    float xscale, yscale;
    float xoffset, yoffset;
    float degs;

    size_t size = PyTuple_Size(args);
    if(size == 8)
    {
        if(!PyArg_ParseTuple(args, "ffffffff", &x, &y, &z, &xscale, &yscale, &xoffset, &yoffset, &degs))
            return NULL;
        sgTextureDrawRads3f2f2f1f(self->texture, x, y, z, xscale, yscale, xoffset, yoffset, degs);
    }
    else if(size == 7)
    {
        if(!PyArg_ParseTuple(args, "fffffff", &x, &y, &xscale, &yscale, &xoffset, &yoffset, &degs))
            return NULL;
        sgTextureDrawRads2f2f2f1f(self->texture, x, y, xscale, yscale, xoffset, yoffset, degs);
    }
    else if(size == 6)
    {
        if(!PyArg_ParseTuple(args, "ffffff", &x, &y, &z, &xscale, &yscale, &degs))
            return NULL;
        sgTextureDrawRads3f2f1f(self->texture, x, y, z, xscale, yscale, degs);
    }
    else if(size == 5)
    {
        if(!PyArg_ParseTuple(args, "fffff", &x, &y, &xscale, &yscale, &degs))
            return NULL;
        sgTextureDrawRads2f2f1f(self->texture, x, y, xscale, yscale, degs);
    }
    else if(size == 4)
    {
        if(!PyArg_ParseTuple(args, "ffff", &x, &y, &z, &degs))
            return NULL;
        sgTextureDrawRads3f1f(self->texture, x, y, z, degs);
    }
    else if(size == 3)
    {
        if(!PyArg_ParseTuple(args, "fff", &x, &y, &degs))
            return NULL;
        sgTextureDrawRads2f1f(self->texture, x, y, degs);
    }
    else
        return NULL;
    Py_RETURN_NONE;
}

/*
    x,y,z,xscale,yscale,oxffset,yoffset
    x,y,xscale,yscale,xoffset,yoffset
    x,y,z,xscale,yscale
    x,y,xscale,yscale
    x,y,z
    x,y
*/
static PyObject* pysTextureDraw(PysTexture* self, PyObject* args)
{
    float x, y, z;
    float xscale, yscale;
    float xoffset, yoffset;

    size_t size = PyTuple_Size(args);
    if(size == 7)
    {
        if(!PyArg_ParseTuple(args, "fffffff", &x, &y, &z, &xscale, &yscale, &xoffset, &yoffset))
            return NULL;
        sgTextureDraw3f2f2f(self->texture, x, y, z, xscale, yscale, xoffset, yoffset);
    }
    else if(size == 6)
    {
        if(!PyArg_ParseTuple(args, "ffffff", &x, &y, &xscale, &yscale, &xoffset, &yoffset))
            return NULL;
        sgTextureDraw2f2f2f(self->texture, x, y, xscale, yscale, xoffset, yoffset);
    }
    else if(size == 5)
    {
        if(!PyArg_ParseTuple(args, "fffff", &x, &y, &z, &xscale, &yscale))
            return NULL;
        sgTextureDraw3f2f(self->texture, x, y, z, xscale, yscale);
    }
    else if(size == 4)
    {
        if(!PyArg_ParseTuple(args, "ffff", &x, &y, &xscale, &yscale))
            return NULL;
        sgTextureDraw2f2f(self->texture, x, y, xscale, yscale);
    }
    else if(size == 3)
    {
        if(!PyArg_ParseTuple(args, "fff", &x, &y, &z))
            return NULL;
        sgTextureDraw3f(self->texture, x, y, z);
    }
    else if(size == 2)
    {
        if(!PyArg_ParseTuple(args, "ff", &x, &y))
            return NULL;
        sgTextureDraw2f(self->texture, x, y);
    }
    else if(size == 0)
        sgTextureDraw(self->texture);
    else
        return NULL;
    Py_RETURN_NONE;
}

static PyObject* pysTextureGetSize(PysTexture* self)
{
    SGuint width, height;
    sgTextureGetSize(self->texture, &width, &height);

    return Py_BuildValue("(II)", width, height);
}
static PyObject* pysTextureGetWidth(PysTexture* self)
{
    return Py_BuildValue("I", sgTextureGetWidth(self->texture));
}
static PyObject* pysTextureGetHeight(PysTexture* self)
{
    return Py_BuildValue("I", sgTextureGetHeight(self->texture));
}

static PyMethodDef PysTextureMethods[] = {
    {"drawRads", (PyCFunction)pysTextureDrawRads, METH_VARARGS, ""},
    {"drawDegs", (PyCFunction)pysTextureDrawDegs, METH_VARARGS, ""},
    {"draw", (PyCFunction)pysTextureDraw, METH_VARARGS, ""},

    {"getSize", (PyCFunction)pysTextureGetSize, METH_NOARGS, ""},
    {"getWidth", (PyCFunction)pysTextureGetWidth, METH_NOARGS, ""},
    {"getHeight", (PyCFunction)pysTextureGetHeight, METH_NOARGS, ""},
    {NULL, NULL, 0, NULL}
};

static PyMemberDef PysTextureMembers[] = {
    {NULL, 0, 0, 0, NULL}
};

static PyTypeObject PysTextureType = {
    PyObject_HEAD_INIT(NULL)
    0,                         /*ob_size*/
    "siege.graphics.Texture",   /*tp_name*/
    sizeof(PysTexture),         /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor)pysTextureDealloc, /*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 */
    PysTextureMethods,          /* tp_methods */
    PysTextureMembers,          /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc)pysTextureInit,   /* tp_init */
    0,                         /* tp_alloc */
    pysTextureNew,                 /* tp_new */
};

int pysTextureCheck(PyObject* o)
{
    return PyObject_TypeCheck(o, &PysTextureType);
}
void sgpyInitGraphicsTexture(PyObject* parent)
{
    PysTextureType.tp_new = PyType_GenericNew;
    if(PyType_Ready(&PysTextureType) < 0)
        return;

    Py_INCREF(&PysTextureType);
    PyModule_AddObject(parent, "Texture", (PyObject*)&PysTextureType);
}
