/*
 * $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.exec;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import com.sun.interview.Question;
import com.sun.interview.Interview;
import com.sun.javatest.ExcludeList;
import com.sun.javatest.InterviewParameters;
import com.sun.javatest.Parameters;
import com.sun.javatest.tool.ToolDialog;
import com.sun.javatest.tool.UIFactory;

class ExcludeListBrowser extends ToolDialog
{
    ExcludeListBrowser(Container parent, UIFactory uif) {
	super(parent, uif, "elb");
	this.params = params;

	listener = new Listener();
    }

    public void show(InterviewParameters params) {
	this.params = params;
	setVisible(true);
    }

    private void updateContent() {
	ExcludeList exclList = params.getExcludeList();
	File[] exclFiles;
	Parameters.ExcludeListParameters eParams =
	    params.getExcludeListParameters();
	if (eParams instanceof Parameters.MutableExcludeListParameters) 
	    exclFiles = ((Parameters.MutableExcludeListParameters) eParams).getExcludeFiles();
	else
	    exclFiles = null;

	// rely on interview caching to allow reference equality here
	if (list != exclList || files != exclFiles)
	    setTable(exclFiles, exclList);
    }

    private void setTable(File[] files, ExcludeList list) {

	this.list = list;
	this.files = files;

	model = new ExcludeListTableModel(list);
	table.setModel(model);

	if (files == null || files.length == 0)
	    setI18NTitle("elb.title0");
	else if (files.length == 1)
	    setI18NTitle("elb.title1", files[0].getPath());
	else 
	    setI18NTitle("elb.titlen", new Integer(files.length));
    }

    protected void initGUI() {
	// fix
	// TO DO...
	//fileField = uif.createOutputField("elb.file", 30);
	//fileField.setBorder(null);
	//fileField.setHorizontalAlignment(JTextField.RIGHT);
	//setHeadExtras(fileField);
	JPanel body = uif.createPanel("elb.body", new GridBagLayout(), false);
	body.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
	int dpi = uif.getDotsPerInch();
	body.setPreferredSize(new Dimension(5 * dpi, 2 * dpi));

	GridBagConstraints c = new GridBagConstraints();
	c.fill = GridBagConstraints.BOTH;
	c.gridwidth = GridBagConstraints.REMAINDER;
	c.weighty = 1;
	c.insets.bottom = 5;
	/*
	list = uif.createList("elb.list");
	list.addListSelectionListener(new ListSelectionListener() {
	    public void valueChanged(ListSelectionEvent e) {
		selectEntry((ExcludeList.Entry)(list.getSelectedValue()));
	    }
	});
	
	list.setCellRenderer(new DefaultListCellRenderer() {	
	    public Component getListCellRendererComponent(JList list, Object o, int index, boolean isSelected, boolean cellHasFocus) {
		String name = entryToString((ExcludeList.Entry)o);
		return super.getListCellRendererComponent(list, name, index, isSelected, cellHasFocus);
	    }
	});
	list.setVisibleRowCount(3);
	body.add(uif.createScrollPane(list), c);
	*/
	table = new JTable();
	table.setRowSelectionAllowed(true);
	table.setColumnSelectionAllowed(false);
	table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
	    public void valueChanged(ListSelectionEvent e) {
		showSelectedEntry();
	    }
	});

        uif.setAccessibleInfo(table, "elb.tbl");
        uif.setToolTip(table, "elb.tbl");
        
	body.add(new JScrollPane(table), c);

	GridBagConstraints lc = new GridBagConstraints();
	lc.insets.top = 2;
	lc.insets.right = 5;
	lc.anchor = GridBagConstraints.EAST;

	GridBagConstraints fc = new GridBagConstraints();
	fc.gridwidth = GridBagConstraints.REMAINDER;
	fc.insets.top = 2;
	fc.weightx = 1;
	fc.fill = GridBagConstraints.HORIZONTAL;

	JLabel synopsisLabel = uif.createLabel("elb.synopsis", true);
	body.add(synopsisLabel, lc);
	synopsisField = uif.createOutputField("elb.synopsis", synopsisLabel);
	body.add(synopsisField, fc);

	JLabel kwLabel = uif.createLabel("elb.kws", true);
	body.add(kwLabel, lc);
	kwField = uif.createOutputField("elb.kws", kwLabel);
	body.add(kwField, fc);

	JLabel bugIdsLabel = uif.createLabel("elb.bugids", true);
	body.add(bugIdsLabel, lc);
	bugIdsField = uif.createOutputField("elb.bugids", bugIdsLabel);
	body.add(bugIdsField, fc);
	
	setBody(body);

	JButton closeBtn = uif.createCloseButton("elb.close");
	setButtons(new JButton[] { closeBtn }, closeBtn);

	setComponentListener(listener);
    }

    private void showSelectedEntry() {
	ExcludeList.Entry e = model.getEntry(table.getSelectedRow());

	if (e == null) {
	    synopsisField.setText("");
	    kwField.setText("");
	    bugIdsField.setText("");
	} 
	else {
	    synopsisField.setText(e.getSynopsis());
	    kwField.setText(getKeywords(e));
	    bugIdsField.setText(getBugIds(e));
	}
    }

    private String entryToString(ExcludeList.Entry e) {
	String u = e.getRelativeURL();
	String tc = e.getTestCases();
	return (tc == null ? u : u + "[" + tc + "]");
    }

    private String getBugIds(ExcludeList.Entry e) {
	String[] bugIds = e.getBugIdStrings();
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < bugIds.length; i++) {
	    if (i > 0)
		sb.append(", ");
	    sb.append(bugIds[i]);
	}
	return sb.toString();
    }

    private String getKeywords(ExcludeList.Entry e) {
	String[] keywords = e.getPlatforms();
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < keywords.length; i++) {
	    if (i > 0)
		sb.append(", ");
	    sb.append(keywords[i]);
	}
	return sb.toString();
    }


    private InterviewParameters params;
    private File[] files;
    private ExcludeList list;

    private ExcludeListTableModel model;
    private JTable table;
    private JTextField synopsisField;
    private JTextField kwField;
    private JTextField bugIdsField;

    private Listener listener;

    private class Listener 
	extends ComponentAdapter
	implements Interview.Observer
    {
	// ComponentListener
	public void componentShown(ComponentEvent e) {
	    params.addObserver(this);
	    updateContent();
	}
	
	public void componentHidden(ComponentEvent e) {
	    params.removeObserver(this);
	}

	// Interview.Observer
	public void currentQuestionChanged(Question q) {
	}

	public void pathUpdated() {
	    updateContent();
	}
    }

    private static final int TEST_NAME_COL = 0;
    private static final int TEST_CASE_COL = 1;
    private static final int BUG_COL = 2;
    private static final int KEYWORDS_COL = 3;
    private static final int SYNOPSIS_COL = 4;
    private static final int COLUMN_COUNT = 5;

    private String[] columnNames;

    private class ExcludeListTableModel implements TableModel
    {
	ExcludeListTableModel(ExcludeList list) {
	    if (columnNames == null) {
		columnNames = new String[COLUMN_COUNT];
		columnNames[TEST_NAME_COL] = uif.getI18NString("elb.col.testName");
		columnNames[TEST_CASE_COL] = uif.getI18NString("elb.col.testCase");
		columnNames[BUG_COL] = uif.getI18NString("elb.col.bugId");
		columnNames[KEYWORDS_COL] = uif.getI18NString("elb.col.keywords");
		columnNames[SYNOPSIS_COL] = uif.getI18NString("elb.col.synopsis");
	    }

	    // The following operation is slow and should arguably be 
	    // done by a worker thread, perhaps using the nested List class as
	    // a Runnable.
	    SortedSet sortedEntries = new TreeSet(new Comparator() {
		    public int compare(Object o1, Object o2) {
			String s1 = entryToString((ExcludeList.Entry)o1);
			String s2 = entryToString((ExcludeList.Entry)o2);
			return s1.compareTo(s2);
		    }
		});

	    if (list != null) {
		for (Iterator iter = list.getIterator(false); iter.hasNext(); ) {
		    ExcludeList.Entry ee = (ExcludeList.Entry) (iter.next());
		    sortedEntries.add(ee);
		}
	    }

	    entries = new ExcludeList.Entry[sortedEntries.size()];
	    sortedEntries.toArray(entries);
	}

	ExcludeList.Entry getEntry(int index) {
	    return (index < 0 || index >= entries.length ? null : entries[index]);
	}

	public void addTableModelListener(TableModelListener l) {
	    // model never changes, so ignore listener
	}

	public Class getColumnClass(int columnIndex) {
	    // for now, all are strings
	    return String.class;
	}

	public int getColumnCount() {
	    return COLUMN_COUNT;
	}

	public String getColumnName(int index) {
	    return columnNames[index];
	}

	public int getRowCount() {
	    return entries.length;
	}

	public Object getValueAt(int rowIndex, int colIndex) {
	    ExcludeList.Entry e = entries[rowIndex];
	    switch (colIndex) {
	    case TEST_NAME_COL:
		return e.getRelativeURL();

	    case TEST_CASE_COL:
		return e.getTestCases();

	    case BUG_COL:
		return getBugIds(e);

	    case KEYWORDS_COL:
		return getKeywords(e);

	    case SYNOPSIS_COL:
		return e.getSynopsis();
	    }

	    throw new IllegalArgumentException();
	}

	public boolean isCellEditable(int rowIndex, int colIndex) {
	    return false;
	}

	public void removeTableModelListener(TableModelListener l) {
	    // model never changes, so ignore listener
	}

	public void setValueAt(Object aValue, int rowIndex, int colIndex) {
	    throw new UnsupportedOperationException();
	}

	private ExcludeList.Entry[] entries;
	
    }
}
