/*
 * Copyright 1999 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

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

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

import java.io.IOException;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

import com.sun.jdi.*;
import com.sun.jdi.connect.*;

import com.sun.tools.example.debug.bdi.*;

class LaunchTool {

    private final ExecutionManager runtime;

    private abstract class ArgRep {
        final Connector.Argument arg;
        final JPanel panel;

        ArgRep(Connector.Argument arg) {
            this.arg = arg;
            panel = new JPanel();
            Border etched = BorderFactory.createEtchedBorder();
            Border titled = BorderFactory.createTitledBorder(etched,
                                      arg.description(),
                                      TitledBorder.LEFT, TitledBorder.TOP);
            panel.setBorder(titled);
        }

        abstract String getText();

        boolean isValid() {
            return arg.isValid(getText());
        }

        boolean isSpecified() {
            String value = getText();
            return (value != null && value.length() > 0) ||
                !arg.mustSpecify();
        }

        void install() {
            arg.setValue(getText());
        }
    }

    private class StringArgRep extends ArgRep {
        final JTextField textField;

        StringArgRep(Connector.Argument arg, JPanel comp) {
            super(arg);
            textField = new JTextField(arg.value(), 50 );
            textField.setBorder(BorderFactory.createLoweredBevelBorder());

            panel.add(new JLabel(arg.label(), SwingConstants.RIGHT));
            panel.add(textField); // , BorderLayout.CENTER);
            comp.add(panel);
        }

        String getText() {
            return textField.getText();
        }
    }

    private class BooleanArgRep extends ArgRep {
        final JCheckBox check;

        BooleanArgRep(Connector.BooleanArgument barg, JPanel comp) {
            super(barg);
            check = new JCheckBox(barg.label());
            check.setSelected(barg.booleanValue());
            panel.add(check);
            comp.add(panel);
        }

        String getText() {
            return ((Connector.BooleanArgument)arg)
                           .stringValueOf(check.getModel().isSelected());
        }
    }


    private LaunchTool(ExecutionManager runtime) {
        this.runtime = runtime;
    }

    private Connector selectConnector() {
        final JDialog dialog = new JDialog();
        Container content = dialog.getContentPane();
        final JPanel radioPanel = new JPanel();
        final ButtonGroup radioGroup = new ButtonGroup();
        VirtualMachineManager manager = Bootstrap.virtualMachineManager();
        List all = manager.allConnectors();
        Map<ButtonModel, Connector> modelToConnector = new HashMap<ButtonModel, Connector>(all.size(), 0.5f);

        dialog.setModal(true);
        dialog.setTitle("Select Connector Type");
        radioPanel.setLayout(new BoxLayout(radioPanel, BoxLayout.Y_AXIS));
        for (Iterator it = all.iterator(); it.hasNext(); ) {
            Connector connector = (Connector)it.next();
            JRadioButton radio = new JRadioButton(connector.description());
            modelToConnector.put(radio.getModel(), connector);
            radioPanel.add(radio);
            radioGroup.add(radio);
        }
        content.add(radioPanel);

        final boolean[] oked = {false};
        JPanel buttonPanel = okCancel( dialog, new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                if (radioGroup.getSelection() == null) {
                    JOptionPane.showMessageDialog(dialog,
                                    "Please select a connector type",
                                    "No Selection",
                                     JOptionPane.ERROR_MESSAGE);
                } else {
                    oked[0] = true;
                    dialog.setVisible(false);
                    dialog.dispose();
                }
            }
        } );
        content.add(BorderLayout.SOUTH, buttonPanel);
        dialog.pack();
        dialog.show();

        return oked[0] ?
            (Connector)(modelToConnector.get(radioGroup.getSelection())) :
            null;
    }

    private void configureAndConnect(final Connector connector) {
        final JDialog dialog = new JDialog();
        final Map<String, Connector.Argument> args = connector.defaultArguments();

        dialog.setModal(true);
        dialog.setTitle("Connector Arguments");
        Container content = dialog.getContentPane();
        JPanel guts = new JPanel();
        Border etched = BorderFactory.createEtchedBorder();
        Border titled = BorderFactory.createTitledBorder(etched,
                                connector.description(),
                                TitledBorder.LEFT, TitledBorder.TOP);
        guts.setBorder(etched);
        guts.setLayout(new BoxLayout(guts, BoxLayout.Y_AXIS));

        //        guts.add(new JLabel(connector.description()));

        final List<ArgRep> argReps = new ArrayList<ArgRep>(args.size());
        for (Iterator it = args.values().iterator(); it.hasNext(); ) {
            Object arg = it.next();
            ArgRep ar;
            if (arg instanceof Connector.BooleanArgument) {
                ar = new BooleanArgRep((Connector.BooleanArgument)arg, guts);
            } else {
                ar = new StringArgRep((Connector.Argument)arg, guts);
            }
            argReps.add(ar);
        }
        content.add(guts);

        JPanel buttonPanel = okCancel( dialog, new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                for (Iterator it = argReps.iterator(); it.hasNext(); ) {
                    ArgRep ar = (ArgRep)it.next();
                    if (!ar.isSpecified()) {
                        JOptionPane.showMessageDialog(dialog,
                                    ar.arg.label() +
                                         ": Argument must be specified",
                                    "No argument", JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                    if (!ar.isValid()) {
                        JOptionPane.showMessageDialog(dialog,
                                    ar.arg.label() +
                                         ": Bad argument value: " +
                                         ar.getText(),
                                    "Bad argument", JOptionPane.ERROR_MESSAGE);
                        return;
                    }
                    ar.install();
                }
                try {
                    if (runtime.explictStart(connector, args)) {
                        dialog.setVisible(false);
                        dialog.dispose();
                    } else {
                        JOptionPane.showMessageDialog(dialog,
                           "Bad arguments values: See diagnostics window.",
                           "Bad arguments", JOptionPane.ERROR_MESSAGE);
                    }
                } catch (VMLaunchFailureException exc) {
                        JOptionPane.showMessageDialog(dialog,
                           "Launch Failure: " + exc,
                           "Launch Failed",JOptionPane.ERROR_MESSAGE);
                }
            }
        } );
        content.add(BorderLayout.SOUTH, buttonPanel);
        dialog.pack();
        dialog.show();
    }

    private JPanel okCancel(final JDialog dialog, ActionListener okListener) {
        JPanel buttonPanel = new JPanel();
        JButton ok = new JButton("OK");
        JButton cancel = new JButton("Cancel");
        buttonPanel.add(ok);
        buttonPanel.add(cancel);
        ok.addActionListener(okListener);
        cancel.addActionListener( new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                dialog.setVisible(false);
                dialog.dispose();
            }
        } );
        return buttonPanel;
    }

    static void queryAndLaunchVM(ExecutionManager runtime)
                                         throws VMLaunchFailureException {
        LaunchTool lt = new LaunchTool(runtime);
        Connector connector = lt.selectConnector();
        if (connector != null) {
            lt.configureAndConnect(connector);
        }
    }
}
