/*
 * Copyright (c) 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <Python.h>
#include <glib/gi18n.h>
#include "streamtuner.h"
#include "pst-category.h"
#include "pst-helpers.h"

/*** attributes **************************************************************/

static PyObject *pst_category_get_name (PSTCategory *self, void *closure);
static int pst_category_set_name (PSTCategory *self, PyObject *value, void *closure);
static PyObject *pst_category_get_label (PSTCategory *self, void *closure);
static int pst_category_set_label (PSTCategory *self, PyObject *value, void *closure);
static PyObject *pst_category_get_url_postfix (PSTCategory *self, void *closure);
static int pst_category_set_url_postfix (PSTCategory *self, PyObject *value, void *closure);
static PyObject *pst_category_get_url_cb (PSTCategory *self, void *closure);
static int pst_category_set_url_cb (PSTCategory *self, PyObject *value, void *closure);

static PyGetSetDef getsetters[] = {
  { "name", (getter) pst_category_get_name, (setter) pst_category_set_name },
  { "label", (getter) pst_category_get_label, (setter) pst_category_set_label },
  { "url_postfix", (getter) pst_category_get_url_postfix, (setter) pst_category_set_url_postfix },
  { "url_cb", (getter) pst_category_get_url_cb, (setter) pst_category_set_url_cb },
  
  { NULL }
};

/*** type object *************************************************************/

static PyObject *pst_category_new (PyTypeObject *type, PyObject *args, PyObject *keywords);
static void pst_category_dealloc (PSTCategory *self);

PyTypeObject PSTCategory_Type = {
  PyObject_HEAD_INIT(NULL)
  0,				/* ob_size */
  "ST.Category",		/* tp_name */
  sizeof(PSTCategory),		/* tp_basicsize */
  0,				/* tp_itemsize */
  (destructor) pst_category_dealloc, /* tp_dealloc */
  NULL,				/* tp_print */
  NULL,				/* tp_getattr */
  NULL,				/* tp_setattr */
  NULL,				/* tp_compare */
  NULL,				/* tp_repr */
  NULL,				/* tp_as_number */
  NULL,				/* tp_as_sequence */
  NULL,				/* tp_as_mapping */
  NULL,				/* tp_hash */
  NULL,				/* tp_call */
  NULL,				/* tp_str */
  NULL,				/* tp_getattro */
  NULL,				/* tp_setattro */
  NULL,				/* tp_as_buffer */
  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
  NULL,				/* tp_doc */
  NULL,				/* tp_traverse */
  NULL,				/* tp_clear */
  NULL,				/* tp_richcompare */
  0,				/* tp_weaklistoffset */
  NULL,				/* tp_iter */
  NULL,				/* tp_iternext */
  NULL,				/* tp_methods */
  NULL,				/* tp_members */
  getsetters,			/* tp_getset */
  NULL,				/* tp_base */
  NULL,				/* tp_dict */
  NULL,				/* tp_descr_get */
  NULL,				/* tp_descr_set */
  0,				/* tp_dictoffset */
  NULL,				/* tp_init */
  NULL,				/* tp_alloc */
  pst_category_new		/* tp_new */
};

/*** function declarations ***************************************************/

static void pst_category_construct (PSTCategory *self);
static gboolean pst_category_url_cb (PythonCategory *category);

/*** type methods ************************************************************/

static PyObject *
pst_category_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
{
  static char *keyword_list[] = { NULL };
  PSTCategory *self;

  if (! PyArg_ParseTupleAndKeywords(args, keywords, "", keyword_list))
    return NULL;

  self = (PSTCategory *) type->tp_alloc(type, 0);
  if (! self)
    return NULL;

  pst_category_construct(self);

  return (PyObject *) self;
}

static void
pst_category_construct (PSTCategory *self)
{
  self->category = g_new0(PythonCategory, 1);
  self->category->p = self;
  self->url_cb = NULL;
}

static void
pst_category_dealloc (PSTCategory *self)
{
  st_category_free((STCategory *) self->category);
  Py_XDECREF(self->url_cb);
  self->ob_type->tp_free((PyObject *) self);
}

static PyObject *
pst_category_get_name (PSTCategory *self, void *closure)
{
  return pst_string_from_string_or_null(((STCategory *) self->category)->name);
}

static int
pst_category_set_name (PSTCategory *self, PyObject *value, void *closure)
{
  return pst_string_dup_string_or_null(value, &((STCategory *) self->category)->name);
}

static PyObject *
pst_category_get_label (PSTCategory *self, void *closure)
{
  return pst_string_from_string_or_null(((STCategory *) self->category)->label);
}

static int
pst_category_set_label (PSTCategory *self, PyObject *value, void *closure)
{
  return pst_string_dup_string_or_null(value, &((STCategory *) self->category)->label);
}

static PyObject *
pst_category_get_url_postfix (PSTCategory *self, void *closure)
{
  return pst_string_from_string_or_null(((STCategory *) self->category)->url_postfix);
}

static int
pst_category_set_url_postfix (PSTCategory *self, PyObject *value, void *closure)
{
  return pst_string_dup_string_or_null(value, &((STCategory *) self->category)->url_postfix);
}

static PyObject *
pst_category_get_url_cb (PSTCategory *self, void *closure)
{
  if (self->url_cb)
    {
      Py_INCREF(self->url_cb);
      return self->url_cb;
    }
  else
    return pst_none();
}

static int
pst_category_set_url_cb (PSTCategory *self, PyObject *value, void *closure)
{
  if (value)
    {
      if (PyCallable_Check(value))
	{
	  Py_INCREF(value);
	  self->url_cb = value;
	  ((STCategory *) self->category)->url_cb = (STCategoryURLCallback) pst_category_url_cb;
	}
      else
	{
	  PyErr_SetString(PyExc_TypeError, _("url_cb must be callable"));
	  return -1;
	}
    }
  else
    {
      self->url_cb = NULL;
      ((STCategory *) self->category)->url_cb = NULL;
    }

  return 0;
}


/*** streamtuner callbacks ***************************************************/

PythonCategory *
pst_category_new_cb (gpointer data)
{
  PSTCategory *p;
  PythonCategory *category;

  PST_THREADS_ENTER

  p = PyObject_New(PSTCategory, &PSTCategory_Type);
  if (p)
    {
      pst_category_construct(p);
      category = p->category;
    }
  else
    {
      PyErr_Print();
      category = NULL;
    }

  PST_THREADS_LEAVE

  return category;
}

void
pst_category_free_cb (PythonCategory *category, gpointer data)
{
  PST_THREADS_ENTER
  Py_DECREF(category->p);
  PST_THREADS_LEAVE
}

static gboolean
pst_category_url_cb (PythonCategory *category)
{
  PyObject *result;

  result = PyObject_CallFunction(category->p->url_cb, "O", category->p);
  if (result)
    {
      int status;

      status = PyObject_IsTrue(result);
      Py_DECREF(result);

      if (status != -1)
	return status;
    }

  PyErr_Print();
  return FALSE;
}

/*** C API *******************************************************************/

gboolean
pst_category_register (PyObject *module)
{
  PyTypeObject *ptr = &PSTCategory_Type;

  g_return_val_if_fail(module != NULL, FALSE);

  if (PyType_Ready(&PSTCategory_Type) < 0)
    return FALSE;

  Py_INCREF(&PSTCategory_Type);
  PyModule_AddObject(module, "Category", (PyObject *) ptr);

  return TRUE;
}

PythonCategory *
pst_category_copy (PythonCategory *category)
{
  PSTCategory *p;

  g_return_val_if_fail(category != NULL, NULL);

  p = PyObject_New(PSTCategory, &PSTCategory_Type);
  if (! p)
    return NULL;
  
  pst_category_construct(p);

  if (category->p->url_cb)
    {
      Py_INCREF(category->p->url_cb);
      p->url_cb = category->p->url_cb;
    }
  
  ((STCategory *) p->category)->name = g_strdup(((STCategory *) category)->name);
  ((STCategory *) p->category)->label = g_strdup(((STCategory *) category)->label);
  ((STCategory *) p->category)->url_postfix = g_strdup(((STCategory *) category)->url_postfix);
  ((STCategory *) p->category)->url_cb = ((STCategory *) category)->url_cb;

  return p->category;
}
