/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 "python_private.h"  // must be first!

#include <qpid/dispatch/error.h>
#include "dispatch_private.h"
#include "entity.h"

struct qd_entity_t {
    PyObject py_object;      /* Any object supporting __set/get_item__, e.g. dict. */
};

static PyObject* qd_entity_get_py(qd_entity_t* entity, const char* attribute) {
    PyObject *py_key = PyUnicode_FromString(attribute);
    if (!py_key) return NULL;   /* Don't set qd_error, caller will set if needed. */
    PyObject *value = PyObject_GetItem((PyObject*)entity, py_key);
    Py_DECREF(py_key);
    return value;
}

bool qd_entity_has(qd_entity_t* entity, const char *attribute) {
    PyObject *value = qd_entity_get_py(entity, attribute);
    Py_XDECREF(value);
    PyErr_Clear();              /* Ignore errors */
    return value != NULL;
}

char *qd_entity_get_string(qd_entity_t *entity, const char* attribute) {
    qd_error_clear();
    PyObject *py_obj = qd_entity_get_py(entity, attribute);
    char *str = py_string_2_c(py_obj);
    Py_XDECREF(py_obj);
    if (!str) qd_error_py();
    return str;
}

long qd_entity_get_long(qd_entity_t *entity, const char* attribute) {
    qd_error_clear();
    PyObject *py_obj = qd_entity_get_py(entity, attribute);
    if (py_obj && !PyLong_Check(py_obj)) {
        // 2.6 PyLong_AsLong fails to 'cast' non-long types
        // so we have to manually cast it first:
        PyObject *py_tmp = PyNumber_Long(py_obj);
        Py_XDECREF(py_obj);
        py_obj = py_tmp;
    }
    long result = py_obj ? PyLong_AsLong(py_obj) : -1;
    Py_XDECREF(py_obj);
    qd_error_py();
    return result;
}

bool qd_entity_get_bool(qd_entity_t *entity, const char* attribute) {
    qd_error_clear();
    PyObject *py_obj = qd_entity_get_py(entity, attribute);
    bool result = py_obj ? PyObject_IsTrue(py_obj) : false;
    Py_XDECREF(py_obj);
    qd_error_py();
    return result;
}


char *qd_entity_opt_string(qd_entity_t *entity, const char* attribute, const char* default_value)
{
    if (qd_entity_has(entity, attribute))
        return qd_entity_get_string(entity, attribute);
    else
        return default_value ? strdup(default_value) : NULL;
}

long qd_entity_opt_long(qd_entity_t *entity, const char* attribute, long default_value) {
    if (qd_entity_has(entity, attribute)) {
        long result = qd_entity_get_long(entity, attribute);
        if (!qd_error_code())
            return result;
    }
    return default_value;
}

bool qd_entity_opt_bool(qd_entity_t *entity, const char* attribute, bool default_value) {
    if (qd_entity_has(entity, attribute)) {
        bool result = qd_entity_get_bool(entity, attribute);
        if (!qd_error_code())
            return result;
    }
    return default_value;
}


/**
 * Set a value for an entity attribute. If py_value == NULL then clear the attribute.
 * If the attribute exists and is a list, append this value to the list.
 *
 * NOTE: This function will Py_XDECREF(py_value).
 */
qd_error_t qd_entity_set_py(qd_entity_t* entity, const char* attribute, PyObject* py_value) {
    qd_error_clear();

    int result = 0;
    PyObject *py_key = PyUnicode_FromString(attribute);
    if (py_key) {
        if (py_value == NULL) {     /* Delete the attribute */
            result = PyObject_DelItem((PyObject*)entity, py_key);
            PyErr_Clear();          /* Ignore error if it isn't there. */
        }
        else {
            PyObject *old = PyObject_GetItem((PyObject*)entity, py_key);
            PyErr_Clear();          /* Ignore error if it isn't there. */
            if (old && PyList_Check(old)) /* Add to list */
                result = PyList_Append(old, py_value);
            else                    /* Set attribute */
                result = PyObject_SetItem((PyObject*)entity, py_key, py_value);
            Py_XDECREF(old);
        }
    }
    Py_XDECREF(py_key);
    Py_XDECREF(py_value);
    return (py_key == NULL || result < 0) ? qd_error_py() : QD_ERROR_NONE;
}

qd_error_t qd_entity_set_string(qd_entity_t *entity, const char* attribute, const char *value) {
    return qd_entity_set_py(entity, attribute, value ? PyUnicode_FromString(value) : 0);
}

qd_error_t qd_entity_set_longp(qd_entity_t *entity, const char* attribute, const long *value) {
    return qd_entity_set_py(entity, attribute, value ? PyLong_FromLong(*value) : 0);
}

qd_error_t qd_entity_set_boolp(qd_entity_t *entity, const char *attribute, const bool *value) {
    return qd_entity_set_py(entity, attribute, value ? PyBool_FromLong(*value) : 0);
}

qd_error_t qd_entity_set_long(qd_entity_t *entity, const char* attribute, long value) {
    return qd_entity_set_longp(entity, attribute, &value);
}

qd_error_t qd_entity_set_bool(qd_entity_t *entity, const char *attribute, bool value) {
    return qd_entity_set_boolp(entity, attribute, &value);
}

qd_error_t qd_entity_clear(qd_entity_t *entity, const char *attribute) {
    return qd_entity_set_py(entity, attribute, 0);
}

#define CHECK(err) if (err) return qd_error_code()

qd_error_t qd_entity_set_list(qd_entity_t *entity, const char *attribute) {
    CHECK(qd_entity_clear(entity, attribute));
    return qd_entity_set_py(entity, attribute, PyList_New(0));
}


qd_error_t qd_entity_set_map(qd_entity_t *entity, const char *attribute) {
    //CHECK(qd_entity_clear(entity, attribute));
    return qd_entity_set_py(entity, attribute, PyDict_New());
}

qd_error_t qd_entity_set_map_key_value_int(qd_entity_t *entity, const char *attribute, const char *key, int value)
{
    if (!key)
        return  QD_ERROR_VALUE;

    PyObject *py_key = PyUnicode_FromString(key);
    PyObject *py_value = PyLong_FromLong(value);
    PyObject *py_attribute = PyUnicode_FromString(attribute);

    qd_error_t ret = QD_ERROR_NONE;

    if (PyDict_Contains((PyObject*)entity, py_attribute) == 1) {
        PyObject* dict = PyDict_GetItem((PyObject*)entity, py_attribute);
        if (PyDict_SetItem(dict, py_key, py_value) < 0)
            ret = QD_ERROR_PYTHON;
    }
    else
        ret = QD_ERROR_VALUE;

    Py_XDECREF(py_key);
    Py_XDECREF(py_value);
    Py_XDECREF(py_attribute);

    return ret;
}

qd_error_t qd_entity_set_map_key_value_string(qd_entity_t *entity, const char *attribute, const char *key, const char *value)
{
    if (!key)
        return  QD_ERROR_VALUE;

    PyObject *py_key = PyUnicode_FromString(key);
    PyObject *py_value = PyUnicode_FromString(value);
    PyObject *py_attribute = PyUnicode_FromString(attribute);

    qd_error_t ret = QD_ERROR_NONE;

    if (PyDict_Contains((PyObject*)entity, py_attribute) == 1) {
        PyObject* dict = PyDict_GetItem((PyObject*)entity, py_attribute);
        if (PyDict_SetItem(dict, py_key, py_value) < 0)
            ret = QD_ERROR_PYTHON;
    }
    else
        ret = QD_ERROR_VALUE;

    Py_XDECREF(py_key);
    Py_XDECREF(py_value);
    Py_XDECREF(py_attribute);

    return ret;
}




qd_error_t qd_entity_set_stringf(qd_entity_t *entity, const char* attribute, const char *format, ...)
{
    // Calculate the size
    char dummy[1];
    va_list ap;
    va_start(ap, format);
    size_t len = vsnprintf(dummy, 1, format, ap);
    va_end(ap);

    char buf[len+1];
    va_start(ap, format);
    vsnprintf(buf, len+1, format, ap);
    va_end(ap);

    return qd_entity_set_string(entity, attribute, buf);
}
