#include "PyLinkedColor.h"

PyGetSetDef PyLinkedColor::getsetters[] = {
    {"r", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Red component",   (void*)0},
    {"g", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Green component", (void*)1},
    {"b", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Blue component",  (void*)2},
    {"a", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Alpha component", (void*)3},
    {NULL}
};

PyLinkedColor::PyLinkedColor(_PyLinkedColorData d)
{
    data = d;
}

PyLinkedColor::PyLinkedColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr<UIDrawable> parent, int index)
{
    data.index = index;
    data.parent = parent;
    data.setter = setter;
    data.getter = getter;
}

PyObject* PyLinkedColor::pyObject()
{
    PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyLinkedColorType, 0);
    PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
    self->data = data;
    return obj;
}

PyLinkedColor PyLinkedColor::fromPy(PyObject* obj)
{
    PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
    return PyLinkedColor(self->data);
}

PyLinkedColor PyLinkedColor::fromPy(PyLinkedColorObject* self)
{
    return PyLinkedColor(self->data);
}

void PyLinkedColor::set(sf::Color color)
{
    auto ptr = data.parent.lock();
    if (ptr)
    {
        if (data.setter)
            data.setter(color);
    }
}

sf::Color PyLinkedColor::get()
{
    auto ptr = data.parent.lock();
    if (ptr)
    {
        if (data.getter)
            return data.getter();
    }
    return sf::Color(0, 0, 0, 0);
}

bool PyLinkedColor::alive()
{
    return !data.parent.lock();
}

std::string PyLinkedColor::field()
{
    switch (data.index)
    {
        case 0:
            return "fill";
            break;
        case 1:
            return "outline";
            break;
        case 2:
            return "background";
            break;
        default:
            return "unknown";
            break;
    }
}

Py_hash_t PyLinkedColor::hash(PyObject* obj)
{
    auto self = (PyLinkedColorObject*)obj;
    Py_hash_t value = 0;
    auto ptr = self->data.parent.lock();
    if (ptr)
    {
        auto color = PyLinkedColor(self->data);
        auto c = linkedcolor.get();
        value += c.r;
        value << 8; value += c.g; 
        value << 8; value += c.b; 
        value << 8; value += c.a;
    }
    if (ptr)
    {
        //value << (sizeof(*UIDrawable) * 8);
        value += reinterpret_cast<Py_hash_t>(&ptr);
    } 

    return value;
}

PyObject* PyLinkedColor::repr(PyObject* obj)
{
    PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
    std::ostringstream ss;
    PyLinkedColor color = PyLinkedColor(self->data);
    sf::Color c = color.get();
    ss << "<Color (" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ") " << color.mode() << ">";

    std::string repr_str = ss.str();
    return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
}


int PyLinkedColor::init(PyLinkedColorObject* self, PyObject* args, PyObject* kwds)
{
    // TODO
    static const char* keywords[] = { "r", "g", "b", "a", nullptr };
    return 0;
}

PyObject* PyLinkedColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
    return (PyObject*)type->tp_alloc(type, 0);
}

PyObject* PyLinkedColor::get_member(PyObject* obj, void* closure)
{
    return Py_None; // TODO
}

int PyLinkedColor::set_member(PyObject* obj, PyObject* value, void* closure)
{
    return 0; // TODO
}
