/*
 * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.example.debug.bdi;

import com.sun.jdi.*;
import com.sun.jdi.connect.LaunchingConnector;
import com.sun.jdi.connect.Connector;
import com.sun.jdi.connect.VMStartException;
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
import java.io.*;
import java.util.Map;
import javax.swing.SwingUtilities;


class ChildSession extends Session {

    private Process process;

    private PrintWriter in;
    private BufferedReader out;
    private BufferedReader err;

    private InputWriter inputWriter;
    private OutputReader outputReader;
    private OutputReader errorReader;

    private InputListener input;
    private OutputListener output;
    private OutputListener error;

    public ChildSession(ExecutionManager runtime,
                        String userVMArgs, String cmdLine,
                        InputListener input,
                        OutputListener output,
                        OutputListener error,
                        OutputListener diagnostics) {
        this(runtime, getVM(diagnostics, userVMArgs, cmdLine),
             input, output, error, diagnostics);
    }

    public ChildSession(ExecutionManager runtime,
                        LaunchingConnector connector,
                        Map<String, Connector.Argument> arguments,
                        InputListener input,
                        OutputListener output,
                        OutputListener error,
                        OutputListener diagnostics) {
        this(runtime, generalGetVM(diagnostics, connector, arguments),
             input, output, error, diagnostics);
    }

    private ChildSession(ExecutionManager runtime,
                        VirtualMachine vm,
                        InputListener input,
                        OutputListener output,
                        OutputListener error,
                        OutputListener diagnostics) {
        super(vm, runtime, diagnostics);
        this.input = input;
        this.output = output;
        this.error = error;
    }

    public boolean attach() {

        if (!connectToVMProcess()) {
            diagnostics.putString("Could not launch VM");
            return false;
        }

        /*
         * Create a Thread that will retrieve and display any output.
         * Needs to be high priority, else debugger may exit before
         * it can be displayed.
         */

        //### Rename InputWriter and OutputReader classes
        //### Thread priorities cribbed from ttydebug.  Think about them.

        OutputReader outputReader =
            new OutputReader("output reader", "output",
                             out, output, diagnostics);
        outputReader.setPriority(Thread.MAX_PRIORITY-1);
        outputReader.start();

        OutputReader errorReader =
            new OutputReader("error reader", "error",
                             err, error, diagnostics);
        errorReader.setPriority(Thread.MAX_PRIORITY-1);
        errorReader.start();

        InputWriter inputWriter =
            new InputWriter("input writer", in, input);
        inputWriter.setPriority(Thread.MAX_PRIORITY-1);
        inputWriter.start();

        if (!super.attach()) {
            if (process != null) {
                process.destroy();
                process = null;
            }
            return false;
        }

        //### debug
        //System.out.println("IO after attach: "+ inputWriter + " " + outputReader + " "+ errorReader);

        return true;
    }

    public void detach() {

        //### debug
        //System.out.println("IO before detach: "+ inputWriter + " " + outputReader + " "+ errorReader);

        super.detach();

        /*
        inputWriter.quit();
        outputReader.quit();
        errorReader.quit();
        */

        if (process != null) {
            process.destroy();
            process = null;
        }

    }

    /**
     * Launch child java interpreter, return host:port
     */

    static private void dumpStream(OutputListener diagnostics,
                                   InputStream stream) throws IOException {
        BufferedReader in =
            new BufferedReader(new InputStreamReader(stream));
        String line;
        while ((line = in.readLine()) != null) {
            diagnostics.putString(line);
        }
    }

    static private void dumpFailedLaunchInfo(OutputListener diagnostics,
                                             Process process) {
        try {
            dumpStream(diagnostics, process.getErrorStream());
            dumpStream(diagnostics, process.getInputStream());
        } catch (IOException e) {
            diagnostics.putString("Unable to display process output: " +
                                  e.getMessage());
        }
    }

    static private VirtualMachine getVM(OutputListener diagnostics,
                                        String userVMArgs,
                                        String cmdLine) {
        VirtualMachineManager manager = Bootstrap.virtualMachineManager();
        LaunchingConnector connector = manager.defaultConnector();
        Map<String, Connector.Argument> arguments = connector.defaultArguments();
        arguments.get("options").setValue(userVMArgs);
        arguments.get("main").setValue(cmdLine);
        return generalGetVM(diagnostics, connector, arguments);
    }

    static private VirtualMachine generalGetVM(OutputListener diagnostics,
                                               LaunchingConnector connector,
                                               Map<String, Connector.Argument> arguments) {
        VirtualMachine vm = null;
        try {
            diagnostics.putString("Starting child.");
            vm = connector.launch(arguments);
        } catch (IOException ioe) {
            diagnostics.putString("Unable to start child: " + ioe.getMessage());
        } catch (IllegalConnectorArgumentsException icae) {
            diagnostics.putString("Unable to start child: " + icae.getMessage());
        } catch (VMStartException vmse) {
            diagnostics.putString("Unable to start child: " + vmse.getMessage() + '\n');
            dumpFailedLaunchInfo(diagnostics, vmse.process());
        }
        return vm;
    }

    private boolean connectToVMProcess() {
        if (vm == null) {
            return false;
        }
        process = vm.process();
        in = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
        //### Note small buffer sizes!
        out = new BufferedReader(new InputStreamReader(process.getInputStream()), 1);
        err = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1);
        return true;
    }

    /**
     *  Threads to handle application input/output.
     */

    private static class OutputReader extends Thread {

        private String streamName;
        private BufferedReader stream;
        private OutputListener output;
        private OutputListener diagnostics;
        private boolean running = true;
        private char[] buffer = new char[512];

        OutputReader(String threadName,
                     String streamName,
                     BufferedReader stream,
                     OutputListener output,
                     OutputListener diagnostics) {
            super(threadName);
            this.streamName = streamName;
            this.stream = stream;
            this.output = output;
            this.diagnostics = diagnostics;
        }

        public void quit() {
            running = false;
        }

        public void run() {
            try {
                int count;
                while (running && (count = stream.read(buffer, 0, 512)) != -1) {
                    if (count > 0) {
                        // Run in Swing event dispatcher thread.
                        final String chars = new String(buffer, 0, count);
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                output.putString(chars);
                            }
                        });
                    }
                    //### Should we sleep briefly here?
                }
            } catch (IOException e) {
                // Run in Swing event dispatcher thread.
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        diagnostics.putString("IO error reading " +
                                              streamName +
                                              " stream of child java interpreter");
                    }
                });
            }
        }
    }

    private static class InputWriter extends Thread {

        private PrintWriter stream;
        private InputListener input;
        private boolean running = true;

        InputWriter(String threadName,
                    PrintWriter stream,
                    InputListener input) {
            super(threadName);
            this.stream = stream;
            this.input = input;
        }

        public void quit() {
            //### Won't have much effect if blocked on input!
            running = false;
        }

        public void run() {
            String line;
            while (running) {
                line = input.getLine();
                stream.println(line);
                // Should not be needed for println above!
                stream.flush();
            }
        }
    }

}
