/*
 * $Id$
 *
 * Copyright 1996-2008 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.javatest.audit;

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.filechooser.FileFilter;

import com.sun.javatest.InterviewParameters;
import com.sun.javatest.TestSuite;
import com.sun.javatest.WorkDirectory;
import com.sun.javatest.tool.Desktop;
import com.sun.javatest.tool.FileHistory;
import com.sun.javatest.tool.TestSuiteChooser;
import com.sun.javatest.tool.Tool;
import com.sun.javatest.tool.ToolDialog;
import com.sun.javatest.tool.UIFactory;
import com.sun.javatest.tool.WorkDirChooser;

class OptionsDialog extends ToolDialog
{
    OptionsDialog(Tool tool, ActionListener okListener, UIFactory uif) {
	super(tool, uif, "opts");
	this.tool = tool;
	this.okListener = okListener;
    }

    void setParameters(InterviewParameters params) {
	if (body == null)
	    initGUI();

	if (params != null) {
	    TestSuite ts = params.getTestSuite();
	    if (ts != null)
		tsField.setSelectedItem(ts.getPath());

	    WorkDirectory wd = params.getWorkDirectory();
	    if (wd != null)
		wdField.setSelectedItem(wd.getPath());

	    File cf = params.getFile();
	    if (cf != null)
		cfField.setSelectedItem(cf.getPath());
	}
    }

    String getTestSuitePath() {
	return (String) (tsField.getSelectedItem());
    }

    String getWorkDirPath() {
	return (String) (wdField.getSelectedItem());
    }

    String getConfigFilePath() {
	return (String) (cfField.getSelectedItem());
    }

    protected void initGUI() {
	setI18NTitle("opts.title");
	listener = new Listener();

	body = uif.createPanel("opts.fields", new GridBagLayout(), false);
	body.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

	GridBagConstraints lc = new GridBagConstraints();
	lc.anchor = GridBagConstraints.EAST;
	lc.insets.right = 10;

	GridBagConstraints fc = new GridBagConstraints();
	fc.fill = GridBagConstraints.HORIZONTAL;
	fc.weightx = 1;

	GridBagConstraints bc = new GridBagConstraints();
	bc.gridwidth = GridBagConstraints.REMAINDER;
	bc.fill = GridBagConstraints.VERTICAL;

	Border smallBorder = BorderFactory.createCompoundBorder(
	    BorderFactory.createEtchedBorder(),
	    BorderFactory.createEmptyBorder(0,3,0,3));

	// test suite
	JLabel tsLabel = uif.createLabel("opts.ts", true);
	body.add(tsLabel, lc);
       
	tsField = uif.createChoice("opts.ts", true, tsLabel);
	tsField.addItem("");
	tsField.addActionListener(listener);
	body.add(tsField, fc);

	tsBtn = uif.createIconButton("opts.ts.browse", listener);
	tsBtn.setBorder(smallBorder);
	body.add(tsBtn, bc);

	// results directory (work directory)
	JLabel wdLabel = uif.createLabel("opts.wd", true);
	body.add(wdLabel, lc);
       
	wdField = uif.createChoice("opts.wd", true, wdLabel);
	wdField.addItem("");
	wdField.addActionListener(listener);
	body.add(wdField, fc);

	wdBtn = uif.createIconButton("opts.wd.browse", listener);
	wdBtn.setBorder(smallBorder);
	body.add(wdBtn, bc);

	// config file
	JLabel cfLabel = uif.createLabel("opts.config", true);
	body.add(cfLabel, lc);
       
	cfField = uif.createChoice("opts.config", true, cfLabel);
	cfField.addItem("");
	cfField.setEditable(true);
	cfField.addActionListener(listener);
	body.add(cfField, fc);

	cfBtn = uif.createIconButton("opts.config.browse", listener);
	cfBtn.setBorder(smallBorder);
	body.add(cfBtn, bc);

	Dimension d = body.getPreferredSize();
	int dpi = uif.getDotsPerInch();
	body.setPreferredSize(new Dimension(Math.max(d.width, 5 * dpi), d.height));
	setBody(body);

	JButton okBtn = uif.createButton("opts.ok", okListener, OK);
	JButton cancelBtn = uif.createCancelButton("opts.cancel");
	setButtons(new JButton[] { okBtn, cancelBtn }, okBtn);

	setComponentListener(listener);
    }

    private void updateFieldChoices() {
	updateTestSuiteChoices();
	updateWorkDirectoryChoices();
	updateConfigFileChoices();
    }

    private void chooseTestSuite() {
	if (testSuiteChooser == null) 
	    testSuiteChooser = new TestSuiteChooser();
	int action = testSuiteChooser.showDialog(tool);
	if (action != JFileChooser.APPROVE_OPTION)
	    return;
	TestSuite ts = testSuiteChooser.getSelectedTestSuite();
	tsField.setSelectedItem(ts.getPath());
    }

    private void updateTestSuiteChoices() {
	// get the paths of currently loaded test suites
	// could move this to TestSuite, and use the dirMap cache
	SortedSet s = new TreeSet();
	Desktop d = tool.getDesktop();
	Tool[] tools = d.getTools();
	if (tools != null) {
	    for (int i = 0; i < tools.length; i++) {
		Tool t = tools[i];
		TestSuite[] tss = t.getLoadedTestSuites();
		if (tss != null) {
		    for (int j = 0; j < tss.length; j++) 
			s.add(tss[j].getPath());
		}
	    }
	}

	setItems(tsField, s); 
	updateWorkDirectoryChoices();
    }

    private void chooseWorkDirectory() {
	if (workDirChooser == null) {
            workDirChooser = new WorkDirChooser(true);
	    workDirChooser.setMode(WorkDirChooser.OPEN_FOR_ANY_TESTSUITE);
	}
	int action = workDirChooser.showDialog(tool);
	if (action != JFileChooser.APPROVE_OPTION)
	    return;
	WorkDirectory wd = workDirChooser.getSelectedWorkDirectory();
	wdField.setSelectedItem(wd.getPath());
    }

    private void updateWorkDirectoryChoices() {
	String tsID = null;
	try {
	    String tsp = (String) (tsField.getSelectedItem());
	    if (tsp != null && tsp.length() > 0) {
		TestSuite ts = TestSuite.open(new File(tsp));
		tsID = ts.getID();
	    }
	}
	catch (Exception e) {
	    // ignore
	}

	// get the paths of currently loaded work directories
	// could move this to WorkDirectory and use the dirMap cache
	SortedSet s = new TreeSet();
	Desktop d = tool.getDesktop();
	Tool[] tools = d.getTools();
	if (tools != null) {
	    for (int i = 0; i < tools.length; i++) {
		Tool t = tools[i];
		WorkDirectory[] wds = t.getLoadedWorkDirectories();
		if (wds != null) {
		    for (int j = 0; j < wds.length; j++) {
			WorkDirectory wd = wds[j];
			if (tsID == null || tsID.equals(wd.getTestSuite().getID()))
			    s.add(wd.getPath());
		    }
		}
	    }
	}
	
	setItems(wdField, s); 
    }

    private void chooseConfigFile() {
	if (configFileChooser == null) {
	    configFileChooser = new JFileChooser();
	    String userDir = System.getProperty("user.dir");
	    if (userDir != null)
		configFileChooser.setCurrentDirectory(new File(userDir));
	    configFileChooser.addChoosableFileFilter(new FileFilter() {
		    public boolean accept(File f) {
			return (f.isDirectory() || f.getPath().endsWith(".jti"));
		    }

		    public String getDescription() {
			return uif.getI18NString("opts.jtiFiles");
		    }
		});
	}
	
	int action = configFileChooser.showOpenDialog(tool);
	if (action != JFileChooser.APPROVE_OPTION)
	    return;

	File cf = configFileChooser.getSelectedFile();
	String cfp;
	if (cf == null)
	    cfp = "";
	else {
	    cfp = cf.getPath();
	    if (!cfp.endsWith(".jti"))
		cfp += ".jti";
	}
	cfField.setSelectedItem(cfp);
    }

    private void updateConfigFileChoices() {
	SortedSet s = new TreeSet();
	String wdp = (String) (wdField.getSelectedItem());
	try {
	    WorkDirectory wd = WorkDirectory.open(new File(wdp));
	    FileHistory history = FileHistory.getFileHistory(wd, "configHistory.jtl");
	    File[] entries = history.getRecentEntries(10);
	    for (int i = 0; i < entries.length; i++) 
		s.add(entries[i].getPath());
	}
	catch (Exception e) {
	    // ignore
	}
	setItems(cfField, s);    
    }

    private void setItems(JComboBox field, SortedSet s) {
	// first, remove unwanted entries from field
	for (int i = field.getItemCount() - 1; i >= 0; i-- ) {
	    String item = (String) (field.getItemAt(i));
	    if (s.contains(item)) {
		// this item is required, so remove it from the
		// set to be added later
		s.remove(item);
	    }
	    else if (item.length() > 0 && !item.equals(field.getSelectedItem()))
		// this item is not required, remove it
		field.removeItemAt(i);
	}
	
	// those items remaining in s need to be added to the field
	for (Iterator iter = s.iterator(); iter.hasNext(); ) 
	    field.addItem(iter.next());
    }

    private Tool tool;
    private ActionListener okListener;
    private JPanel body;

    private JComboBox tsField;
    private JButton tsBtn;
    private TestSuiteChooser testSuiteChooser;

    private JComboBox wdField;
    private JButton wdBtn;
    private WorkDirChooser workDirChooser;

    private JComboBox cfField;
    private JButton cfBtn;
    private JFileChooser configFileChooser;

    private Listener listener;

    static final String OK = "OK";

    private class Listener 
	extends ComponentAdapter
	implements ActionListener 
    {
	// ComponentListener
	public void componentShown(ComponentEvent e) {
	    updateFieldChoices();	
	}

	// ActionListener
	public void actionPerformed(ActionEvent e) {
	    Object src = e.getSource();
	    if (src == tsField)
		updateWorkDirectoryChoices();
	    else if (src == tsBtn)
		chooseTestSuite();
	    else if (src == wdField) 
		updateConfigFileChoices();
	    else if (src == wdBtn)
		chooseWorkDirectory();
	    else if (src == cfBtn)
		chooseConfigFile();
	}
    };
    
}
