/* ====================================================================
 * Copyright (c) 2004-2005 Open Source Applications Foundation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions: 
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software. 
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 * ====================================================================
 */

#include "PyLucene.h"

#include <java/lang/StringBuffer.h>
#include <java/io/IOException.h>

#include "org/osafoundation/io/PythonReader.h"
#include "org/osafoundation/util/PythonException.h"

/**
 * The native functions declared in org.osafoundation.io.PythonReader
 * 
 * @author Andi Vajda
 */

namespace org {
    namespace osafoundation {
        namespace io {

            void PythonReader::incRef(void)
            {
                PythonGIL gil;
                Py_INCREF(*(PyObject **) &pythonReader);
            }

            void PythonReader::decRef(void)
            {
                finalizeObject(pythonReader);
            }

            void PythonReader::close(void)
            {
                PythonGIL gil;
                PyObject *result = callPython(*(PyObject **) &pythonReader, "close", NULL);

                if (!result)
                    throw new org::osafoundation::util::PythonException();
                Py_DECREF(result);
            }

            jint PythonReader::read(jcharArray buf, jint offset, jint len)
            {
                PythonGIL gil;
	        int size = buf->length;
		
		if (offset + len > size)
		    len = size - offset;

                PyObject *pyLen = PyInt_FromLong((long) len);
		PyObject *reader = *(PyObject **) &pythonReader;
                PyObject *result = callPython(reader, "read", pyLen, NULL);

                Py_DECREF(pyLen);

                if (result)
                {
                    if (!PyUnicode_CheckExact(result))
                    {
                        PyObject *type =
                            PyObject_Str((PyObject *) result->ob_type);

                        PyErr_Format(PyExc_TypeError,
                                     "expecting a unicode string but got %s",
                                     PyString_AsString(type));
                        Py_DECREF(type);
                        Py_DECREF(result);

                        throw new org::osafoundation::util::PythonException();
                    }

                    PyUnicodeObject *s = (PyUnicodeObject *) result;
                    int length = s->length;

                    if (length == 0)
                    {
                        Py_DECREF(s);
                        return -1;
                    }
                    else if (length > len)
                    {
                        char msg[128];

                        sprintf(msg, "read %d chars but asked for %d",
                                length, len);
                        Py_DECREF(s);
                        throw new java::io::IOException(JvNewStringUTF(msg));
                    }
                    else
                    {
                        jchar *dest = elements(buf) + offset;
                        Py_UNICODE *src = PyUnicode_AS_UNICODE(s);
                        int i = 0;

                        while (i++ < length)
			    *dest++ = *src++;
                        Py_DECREF(s);

                        return length;
                    }
                }
                else
                    throw new org::osafoundation::util::PythonException();
            }
        }
    }
}
