/* sython */
#include "Python.h"

/**
 * Sython misc support functions
 * @author Michael Gaiman
 * @version 1 2/10
 */
 
/* Security Exception*/
PyObject *SySecurityError;

/**
 * Initialize misc. sython variables
 */
void Sy_Init(){
    SySecurityError = PyErr_NewException("exceptions.SySecurityError", NULL, NULL);
    Py_INCREF(SySecurityError);
}

/**
 * Import any python modules that Sython needs to operate.
 */
void Sy_ImportModules(){
    /*PyObject* comm_mod;
    comm_mod=PyImport_ImportModule("sython.comm");
    if(comm_mod == NULL){
        printf("Can't import sython.comm\n");
    }
    Py_DECREF(comm_mod);*/
    PyRun_SimpleString("import sython.comm\n");
    
}

/**
 * Call a python callable object.
 * Note: Module must already have been imported!
 */
PyObject* Sy_CallObject(char* module,char* function,PyObject* args){
    PyObject *mod,*moduledict,*func,*retval;
    /*based upon code from 
    http://mail.python.org/pipermail/python-list/1999-April/000161.html*/
    
    mod = PyImport_AddModule(module);
    if(mod == NULL)
        return NULL;
    Py_INCREF(mod);
    moduledict = PyModule_GetDict(mod);
    Py_INCREF(moduledict);
    func = PyDict_GetItemString(moduledict, function);
    Py_DECREF(moduledict);
    if(func==NULL)
        return NULL;
    Py_INCREF(func);
    retval = PyEval_CallObjectWithKeywords(func, args, (PyObject
    *)NULL);
    Py_DECREF(func);
    Py_DECREF(mod);
    return retval;
}

/**
 * Sends a NEW_SESSION message to sythond if needed.  Returns true if now logged
 * in.  0 If there was an error (In which case an exception is set).
 */
int Sy_ConnectIfNeeded(){
    if(!PyObject_IsTrue(Sy_CallObject("sython.comm","hasSession",NULL))){
        Sy_CallObject("sython.comm","newSession",NULL);
        if(!PyObject_IsTrue(Sy_CallObject("sython.comm","hasSession",NULL))){
            PyErr_SetString(PyExc_IOError,"Could not start session with sythond");
            return 0;
        }
    }
    return 1;
}

/** 
 * Parses tuple for a syobj, retrieves the ID and then packages it in a tuple.
 * Returns NULL if there is an error (after having set an exception).
 */
PyObject*
Sy_PackageID(PyObject *args){
    PyObject *ob,*t;
    if(!PyArg_ParseTuple(args, "O",&ob)){
        return NULL;
    }
    Py_INCREF(ob);
    /*now check to make sure it is a sython object (easier than modifying parsetuple)*/
    if(!PyObject_TypeCheck(ob,&SyObj_Type)){
        PyErr_SetString(PyExc_TypeError,"Sython Object required");
        return NULL;
    }
    t=Py_BuildValue("(S)",((syobj*)ob)->id);
    Py_DECREF(ob);
    return t;
}