//# PythonInterpreter.cc: Interface for connecting and running tasks in Python.
//# Copyright (C) 2005
//# Associated Universities, Inc. Washington DC, USA.
//#
//# This library is free software; you can redistribute it and/or modify it
//# under the terms of the GNU Library General Public License as published by
//# the Free Software Foundation; either version 2 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 Library General Public
//# License for more details.
//#
//# You should have received a copy of the GNU Library General Public License
//# along with this library; if not, write to the Free Software Foundation,
//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
//#
//# Correspondence concerning AIPS++ should be addressed as follows:
//#        Internet email: aips2-request@nrao.edu.
//#        Postal address: AIPS++ Project Office
//#                        National Radio Astronomy Observatory
//#                        520 Edgemont Road
//#                        Charlottesville, VA 22903-2475 USA
//#
//# $Id: $
#include <casaqt/QtParamGui/PythonInterpreter.h>
#include <Python.h>

using namespace casacore;
namespace casa {

// PYTHONINTERPRETER DEFINITIONS //

PythonInterpreter::PythonInterpreter(PyObject* shell) : m_shell(shell) {
    m_initialized = m_shell != NULL;
    m_standalone = m_shell == NULL;
    if(m_shell != NULL) Py_DECREF(m_shell);
}

PythonInterpreter::~PythonInterpreter() {
    if(m_standalone && m_initialized) {
        // can't call Py_Finalize because destruction of modules and objects is
        // random and causes segfaults after the logger is destroyed
        // Py_Finalize();
        
        // call taskmanager::finalize because otherwise a stray process sticks
        // around indefinitely
        PyRun_String("tm.finalize()", Py_file_input, m_shell, m_shell);
    } else if(!m_standalone && m_shell != NULL) {
        PyGILState_STATE gstate;
        gstate = PyGILState_Ensure();
        Py_DECREF(m_shell);
        PyGILState_Release(gstate);
    }
}

bool PythonInterpreter::init(bool showLogger) {
    if(m_shell == NULL && m_standalone && !m_initialized) {
        try {
            String casapylib = pythonPath();
            if(casapylib.empty()) return false;
            
            // use the right python
            stringstream ss;
            ss << casapylib << "/bin";
            char* p = getenv("PATH");
            if(p) ss << ':' << p;            
            setenv("PATH", ss.str().c_str(), 1);
    
            Py_Initialize();
    
            String cp = casapyPath();
            if(!cp.empty()) {
                // set up environment for casapy
                stringstream commands;
                commands << "import sys";
                commands << "\nsys.path += ['" << cp << "', '" << casapylib;
                commands << "/lib/python2.5', '" << casapylib;
                commands << "/lib/python2.5/site-packages']\nsys.argv = [";
                if(!showLogger) commands << "'--nologger', ";
                commands << "]\nexecfile('" << cp;
                commands << "/casapy.py')";
    
                PyRun_SimpleString(commands.str().c_str());
                
                // grab handle to interpreter
                m_shell = PyModule_GetDict(PyImport_AddModule("__main__"));           
            }
            m_initialized = Py_IsInitialized();        
        } catch(...) { m_initialized = false; }
    }
    return m_initialized;
}

void PythonInterpreter::command(String command) {
    if(m_initialized) {
        stringstream ss;
        // print then run the command
        ss << "print \"--> " << command << "\"\n" << command;
        if(m_standalone)
            PyRun_String(ss.str().c_str(), Py_file_input, m_shell, m_shell);
        else {
            PyGILState_STATE gstate;
            gstate = PyGILState_Ensure();
            PyObject_CallMethod(m_shell, "runlines", "s", ss.str().c_str());
            PyGILState_Release(gstate);
        }
    }
}

}