/* -*- Mode: C; c-basic-offset: 4 -*-
 * pygtk- Python bindings for the GTK toolkit.
 * Copyright (C) 2006  Johannes Hölzl
 *
 *   pygoptioncontext.c: GOptionContext wrapper
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include "pygobject-private.h"

static int
pyg_option_context_init(PyGOptionContext *self, 
                        PyObject *args,
                        PyObject *kwargs)
{
    char *parameter_string;
    if (! PyArg_ParseTuple(args, "s:gobject.GOptionContext.__init__", &parameter_string))
        return -1;
    
    self->context = g_option_context_new(parameter_string);
    return 0;
}

static void
pyg_option_context_dealloc(PyGOptionContext *self)
{
    Py_XDECREF(self->main_group);
    self->main_group = NULL;
    
    if(self->context != NULL)
    {
        g_option_context_free(self->context);
        self->context = NULL;
    }

    PyObject_Del(self);
}

static PyObject *
pyg_option_context_parse(PyGOptionContext *self, PyObject *argv)
{
    PyObject *arg;
    PyObject *new_argv;
    gssize argv_length, pos;
    char **argv_content, **original;
    GError *error = NULL;
    gboolean result;
    
    argv_length = PySequence_Size(argv);
    if(argv_length == -1)
    {
        PyErr_SetString(PyExc_TypeError, 
                        "GOptionContext.parse expects a list of strings.");
        return NULL;
    }
    
    argv_content = g_new(char*, PySequence_Size(argv) + 1);
    argv_content[argv_length] = NULL;
    for(pos = 0; pos < argv_length; pos++)
    {
        arg = PySequence_GetItem(argv, pos);
        argv_content[pos] = g_strdup(PyString_AsString(arg));
        if(argv_content[pos] == NULL)
        {
            g_strfreev(argv_content);
            return NULL;
        }
    }
    original = g_memdup(argv_content, sizeof(char*) * (PySequence_Size(argv) + 1));
    
    pyg_begin_allow_threads;
    result = g_option_context_parse(self->context, &argv_length, &argv_content, &error);
    pyg_end_allow_threads;

    if(! result)
    {
        g_free(argv_content);
        g_strfreev(original);
        pyg_error_check(&error);
        return NULL;
    }
    
    new_argv = PyList_New(0);
    for(pos = 0; pos < argv_length; pos++)
    {
        arg = PyString_FromString(argv_content[pos]);
        PyList_Append(new_argv, arg);
    }
    
    g_strfreev(original);
    g_free(argv_content);
    return new_argv;
}

static PyObject *
pyg_option_context_set_help_enabled(PyGOptionContext *self,
                                    PyObject *enabled)
{
    g_option_context_set_help_enabled(self->context, PyObject_IsTrue(enabled));
    Py_RETURN_NONE;
}

static PyObject *
pyg_option_context_get_help_enabled(PyGOptionContext *self)
{
    return PyBool_FromLong(g_option_context_get_help_enabled(self->context));
}

static PyObject *
pyg_option_context_set_ignore_unknown_options(PyGOptionContext *self,
                                              PyObject *ignore)
{
    g_option_context_set_ignore_unknown_options(self->context, 
                                                PyObject_IsTrue(ignore));
    Py_RETURN_NONE;
}

static PyObject *
pyg_option_context_get_ignore_unknown_options(PyGOptionContext *self)
{
    return PyBool_FromLong(
        g_option_context_get_ignore_unknown_options(self->context));
}

static PyObject *
pyg_option_context_set_main_group(PyGOptionContext *self,
                                  PyObject *group)
{
    GOptionGroup* g_group;
    if(PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) {
        PyErr_SetString(PyExc_TypeError, "GOptionContext.set_main_group expects a GOptionGroup.");
        return NULL;
    }
    g_group = pyg_option_group_transfer_group((PyGOptionGroup*) group);
    if(g_group == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Group is already in a OptionContext.");
        return NULL;
    }

    g_option_context_set_main_group(self->context, g_group);
    Py_IncRef(group);
    self->main_group = (PyGOptionGroup*) group;
    
    Py_RETURN_NONE;
}

static PyObject *
pyg_option_context_get_main_group(PyGOptionContext *self)
{
    if(self->main_group == NULL)
        Py_RETURN_NONE;
        
    Py_INCREF(self->main_group);
    return (PyObject*) self->main_group;
}

static PyObject *
pyg_option_context_add_group(PyGOptionContext *self,
                             PyObject *group)
{
    GOptionGroup* g_group;
    if(PyObject_IsInstance(group, (PyObject*) &PyGOptionGroup_Type) != 1) {
        PyErr_SetString(PyExc_TypeError, "GOptionContext.add_group expects a GOptionGroup.");
        return NULL;
    }
    g_group = pyg_option_group_transfer_group((PyGOptionGroup*) group);
    if(g_group == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Group is already in a OptionContext.");
        return NULL;
    }
    g_option_context_add_group(self->context, g_group);
    Py_IncRef(group);
    
    Py_RETURN_NONE;
} 

static PyObject*
pyg_option_context_add_main_entries(PyGOptionContext *self, PyObject *args)
{
    PyObject *entries, *domain = NULL, *func_name;
    
    if(! PyArg_ParseTuple(args, "O|O:OptionContext.add_main_entries", &entries, &domain))
        return NULL;
    
    if(self->main_group == NULL) {
        self->main_group = (PyGOptionGroup*) PyObject_CallFunctionObjArgs(
            (PyObject*) &PyGOptionGroup_Type, Py_None, Py_None, Py_None, NULL);
        g_option_context_set_main_group(self->context, self->main_group->group); 
    }

    func_name = PyString_FromString("add_entries");
    if(PyObject_CallMethodObjArgs((PyObject *) self->main_group, func_name, entries, NULL) == NULL)
    {
        Py_DECREF(func_name);
        return NULL;
    }
        
    Py_DECREF(func_name);

    if(domain != NULL)
    {
        func_name = PyString_FromString("set_translation_domain");
        if(PyObject_CallMethodObjArgs((PyObject *) self->main_group, func_name, domain, NULL) == NULL)
        {
            Py_DECREF(func_name);
            return NULL;
        }
        
        Py_DECREF(func_name);
    }

    Py_RETURN_NONE;
    
        
}

static int
pyg_option_context_compare(PyGOptionContext *self, PyGOptionContext *v)
{
    if (self->context == v->context) return 0;
    if (self->context > v->context) return -1;
    return 1;
}

static PyMethodDef pyg_option_context_methods[] = {
    { "parse", (PyCFunction)pyg_option_context_parse, METH_O },
    { "set_help_enabled", (PyCFunction)pyg_option_context_set_help_enabled, METH_O },
    { "get_help_enabled", (PyCFunction)pyg_option_context_get_help_enabled, METH_NOARGS },
    { "set_ignore_unknown_options", (PyCFunction)pyg_option_context_set_ignore_unknown_options, METH_O },
    { "get_ignore_unknown_options", (PyCFunction)pyg_option_context_get_ignore_unknown_options, METH_NOARGS },
    { "add_main_entries", (PyCFunction)pyg_option_context_add_main_entries, METH_VARARGS },
    { "set_main_group", (PyCFunction)pyg_option_context_set_main_group, METH_O },
    { "get_main_group", (PyCFunction)pyg_option_context_get_main_group, METH_NOARGS },
    { "add_group", (PyCFunction)pyg_option_context_add_group, METH_O },
    { NULL, NULL, 0 },
};

PyTypeObject PyGOptionContext_Type = {
    PyObject_HEAD_INIT(NULL)
    0,
    "gobject.OptionContext",
    sizeof(PyGMainContext),
    0,
    /* methods */
    (destructor)pyg_option_context_dealloc,
    (printfunc)0,
    (getattrfunc)0,
    (setattrfunc)0,
    (cmpfunc)pyg_option_context_compare,
    (reprfunc)0,
    0,
    0,
    0,
    (hashfunc)0,
    (ternaryfunc)0,
    (reprfunc)0,
    (getattrofunc)0,
    (setattrofunc)0,
    0,
    Py_TPFLAGS_DEFAULT,
    NULL,
    (traverseproc)0,
    (inquiry)0,
    (richcmpfunc)0,
    0,
    (getiterfunc)0,
    (iternextfunc)0,
    pyg_option_context_methods,
    0,
    0,
    NULL,
    NULL,
    (descrgetfunc)0,
    (descrsetfunc)0,
    0,
    (initproc)pyg_option_context_init,
};

PyObject * 
pyg_option_context_new (GOptionContext *context)
{
    PyGOptionContext *self;

    self = (PyGOptionContext *)PyObject_NEW(PyGOptionContext,
					    &PyGOptionContext_Type);
    if (self == NULL)
	return NULL;

    self->context = context;
    self->main_group = NULL;
    
    return (PyObject *)self;
}
