/* 
 * JGimp - A Java extension for the GIMP
 * Copyright (C) 2002  Georgia Tech Research Corp.
 * Written by Michael Terry, mterry@cc.gatech.edu
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package org.gimp.jgimp.jython;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.Writer;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;

import org.gimp.jgimp.GimpApp;
import org.python.core.Py;
import org.python.core.PyException;
import org.python.core.PyObject;
import org.python.util.PythonInterpreter;

/**
 * A very simple panel for entering Jython commands interactively
 */
public class InteractiveJythonInterpreter extends JPanel {

    private PythonInterpreter m_Interpreter = null;
    private JFrame m_Frame = null;
    private JTextArea m_InputPane = null;
    private JTextArea m_OutputPane = null;
    private boolean m_NeedExtraReturn = false;
    private GimpApp m_App = null;

    private class InternalWriter extends Writer {

        public void write(char[] chars, int offset, int length) throws IOException {
            String s = new String(chars, offset, length);
            m_OutputPane.append(s);
        }
        public void flush() throws IOException {
            ; // no-op
        }
        public void close() throws IOException {
            ; // no-op
        }
    }

    public InteractiveJythonInterpreter(JGimpJythonInterpreter interpreter, GimpApp app) {
		m_App = app;
        m_Interpreter = interpreter.getInterpreter();
        InternalWriter writer = new InternalWriter();
        m_Interpreter.setErr(writer);
        m_Interpreter.setOut(writer);

        m_InputPane = new JTextArea();
        m_OutputPane = new JTextArea();
        m_OutputPane.setEditable(false);

        m_InputPane.setSize(new Dimension(200, 100));
        m_OutputPane.setSize(new Dimension(200, 300));

        m_OutputPane.setLineWrap(true);
        m_InputPane.setLineWrap(false);

        JScrollPane topScrollPane =
            new JScrollPane(
                m_OutputPane,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        JScrollPane bottomScrollPane =
            new JScrollPane(
                m_InputPane,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        this.setLayout(new GridLayout(1, 1));
        JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topScrollPane, bottomScrollPane);
        splitPane.setResizeWeight(1);
        this.add(splitPane);

        m_InputPane.addKeyListener(new KeyAdapter() {

            public void keyReleased(KeyEvent key) {
                if (key.getKeyCode() == KeyEvent.VK_ENTER) {
                    String command = m_InputPane.getText();
					if (command.length() < 1) {
						return;
					}
                    command = command.substring(0, command.length() - 1);
                    if (command.length() == 0) {
                        m_InputPane.setText("");
                    } else {
                        executeCommand(command);
                    }
                }
            }

        });

        m_InputPane.requestFocus();
    }

    public PythonInterpreter getInterpreter() {
        return m_Interpreter;
    }

    private void executeCommand(String source) {
        PyObject code;

        if (m_NeedExtraReturn) {
            if (!source.endsWith("\n")) {
                return;
            }
        }
        try {
            code = org.python.modules.codeop.compile_command(source);
        } catch (PyException exc) {
            if (Py.matchException(exc, Py.SyntaxError)
                || Py.matchException(exc, Py.ValueError)
                || Py.matchException(exc, Py.OverflowError)) {

                m_OutputPane.append(exc.toString() + "\n");
                return;
            } else {
                throw exc;
            }
        }
        if (code == Py.None) {
            // no code yet, so ignore for now...
            m_NeedExtraReturn = true;
            return;
        }

        try {
            if (m_NeedExtraReturn) {
                m_OutputPane.append(">>> " + source.substring(0, source.length()));
            } else {
                m_OutputPane.append(">>> " + source + "\n");
            }
            m_Interpreter.exec(code);
        } catch (Exception e) {
            m_OutputPane.append(e.toString());
        }
        m_InputPane.setText("");
        m_NeedExtraReturn = false;
    }
    /**
     * @see org.gimp.jgimp.plugin.JGimpPlugIn#getPlugInInfo(org.gimp.jgimp.GimpApp)
     *
    public JGimpProcedureDescriptor[] getPlugInInfo(GimpApp app) {

        JGimpParamDescriptor[] pdbParams = new JGimpParamDescriptor[3];
        pdbParams[0] = new JGimpParamDescriptor( JGimpPDBArgTypeConstants.PDB_INT32,
                                                 "run_mode",
                                                 "Interactive, non-interactive" ); // Can run interactively, or non-interactively
        pdbParams[1] = new JGimpParamDescriptor( JGimpPDBArgTypeConstants.PDB_IMAGE,
                                                 "image",
                                                 "Input image" ); // The image we're going to work on
        pdbParams[2] = new JGimpParamDescriptor( JGimpPDBArgTypeConstants.PDB_DRAWABLE,
                                                 "drawable",
                                                 "Input drawable"); // The drawable we're going to work on
        JGimpProcedureDescriptor theDescription =
            new JGimpProcedureDescriptor(
                "jython-interactive-interpreter",
                "Interactive Jython Interpreter",
                "Run this to interactively enter commands to control the GIMP",
                "Michael Terry",
                "2003, Georgia Tech Research Institution",
                "April 2003",
                JGimpMenuPathConstructor.createToolboxMenuPath("Xtns/Jython/Jython Console"),
                JGimpImageTypeConstructor.createAnyImageType().toString(),
                pdbParams,
                null);
        return new JGimpProcedureDescriptor[] { theDescription };
    }
	*/


    public void run() {
        if (m_Frame == null) {
            m_Frame = new JFrame("Jython interactive interpreter");
            m_Frame.getContentPane().add(this);
            m_Frame.pack();
            m_Frame.setSize(200, 300);
        }
        m_Frame.setVisible(true);
    }

}
