/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/

package installer;

/*
 * Welcome.java
 *
 * Created on 04 July 2002, 15:43
 */

/**
 *
 * @author  mike
 */

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.SwingUtilities.*;

public class IdeVersion extends javax.swing.JPanel implements ActionListener, TableModelListener {
    
    /** Creates new form Welcome */
    public IdeVersion(InstallWizard wizard) {
        this.wizard=wizard;
	setBackground(Color.white);
        initComponents();
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {
        Properties props = null;
        JPanel versionPanel = new JPanel();
        setLayout(new BorderLayout());


	try {
        	//props = InstUtil.getNetbeansLocation();
		
		Properties netbeansProps = InstUtil.getNetbeansLocation();
		//Properties jeditProps = InstUtil.getJeditLocation();
		Properties ideProps = new Properties();
		if(netbeansProps!=null )
		{
                System.out.println("**** Found netbeans install");
		for( int n = 0; n < netbeansProps.size(); n++ ) {
			for( int v = 0; v < InstUtil.versions.length; v++ ) {
				System.out.println("n: " +n+" v: " +v);
				String key = InstUtil.versions[v];
				System.out.println("It got here1");
				String path = null;
				if ( (path = netbeansProps.getProperty(key) ) != null ) {
					//System.out.println( "n="+n+" v="+v + " Netbeans " + " key=" + key + " path=" + path );
					ideProps.put(key, path);
				}
			}
		}
		}
                //System.out.println("*** About to look for jedit install");
		/*
		if(jeditProps!=null)
		{
			for( int j = 0; j < jeditProps.size(); j++ ) {
				for( int v = 0; v < InstUtil.versions.length; v++ ) {
				System.out.println("j: " +j+" v: " +v);
					String key = InstUtil.versions[v];
					String path = null;
					if ((path = jeditProps.getProperty(key)) != null) {
						//System.out.println( "j="+j+" v="+v + " jEdit " + " key=" + key + " path=" + path );
						ideProps.put(key, path);
					}			
				}			
			}		
		}
		*/
		props = ideProps;
	}
        catch (IOException eIO) {
            System.err.println("Failed to parse .netbeans/ide.log");
	    //JOptionPane.showMessageDialog(this, "There was a problem reading from the NetBeans ide.log file.", "Parse Error", JOptionPane.ERROR_MESSAGE);			
        }
        catch (Exception e) {
            System.err.println("Exception thrown in initComponents");
        }
	
	tableModel = new MyTableModelIDE (props, InstUtil.versions);

	if (tableModel.getRowCount() == 0)
	{
            JOptionPane.showMessageDialog(this, "No compatible IDEs were found.", "Invalid versions", JOptionPane.ERROR_MESSAGE);			
            //wizard.exitForm(null);
	}

        tableModel.addTableModelListener(this);
        JTable tableVersions = new JTable(tableModel) {
            public String getToolTipText(MouseEvent event)
            {
                int col = columnAtPoint( event.getPoint() );
                if (col != 2)
                    return null;

                int row = rowAtPoint( event.getPoint() );
                Object o = getValueAt(row, col);

                if (o == null)
                    return null;

                if (o.toString().equals(""))
                    return null;

                return o.toString();
            }

            public Point getToolTipLocation(MouseEvent event)
            {
                int col = columnAtPoint( event.getPoint() );
                if (col != 2)
                    return null;

                int row = rowAtPoint( event.getPoint() );
                Object o = getValueAt(row,col);

                if (o == null)
                    return null;

                if (o.toString().equals(""))
                    return null;

                Point pt = getCellRect(row, col, true).getLocation();
                pt.translate(-1,-2);
                return pt;
            }
        };

        JScrollPane scroll = new JScrollPane(tableVersions);

        tableVersions.setPreferredSize(
            new Dimension(InstallWizard.DEFWIDTH,InstallWizard.DEFHEIGHT));

        tableVersions.setRowSelectionAllowed(false);
        tableVersions.setColumnSelectionAllowed(false);
        tableVersions.setCellSelectionEnabled(false);

        initColumnSizes(tableVersions, tableModel);
        versionPanel.add(scroll);

        JTextArea area = new JTextArea("Please select IDEs below that you wish to add Scripting support to");
        area.setLineWrap(true);
        area.setEditable(false);
        add(area, BorderLayout.NORTH);
        add(versionPanel, BorderLayout.CENTER);
        nav = new NavPanel(wizard, true, false, true, InstallWizard.IDEWELCOME, InstallWizard.IDEFINAL);
        nav.setNextListener(this);
        add(nav, BorderLayout.SOUTH);    
        
    }// initComponents
    
    
    public java.awt.Dimension getPreferredSize() {
        return new java.awt.Dimension(320, 280);
    }
    
    
    public void actionPerformed(ActionEvent ev) {
        wizard.clearLocations();
        int len = tableModel.data.size();
        for (int i = 0; i < len; i++) {
            ArrayList list = (ArrayList)tableModel.data.get(i);
            if (((Boolean)list.get(0)).booleanValue() == true)
                wizard.storeLocation((String)list.get(2));
        }
        
        //System.out.println(wizard.getLocations());
    }
    
    
    public void tableChanged(TableModelEvent e) {
        if (tableModel.isAnySelected()) {
            nav.enableNext(true);
        }
        else {
            nav.enableNext(false);
        }
    }
    
    private void initColumnSizes(JTable table, MyTableModelIDE model) {
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        int preferredWidth = 0;
        int totalWidth = 0;
        Object[] longValues = model.longValues;

        for (int i = 0; i < 3; i++) {
            column = table.getColumnModel().getColumn(i);

            try {
                comp = column.getHeaderRenderer().
                             getTableCellRendererComponent(
                                 null, column.getHeaderValue(), 
                                 false, false, 0, 0);
                headerWidth = comp.getPreferredSize().width;
            } catch (NullPointerException e) {
                // System.err.println("Null pointer exception!");
                // System.err.println("  getHeaderRenderer returns null in 1.3.");
                // System.err.println("  The replacement is getDefaultRenderer.");
            }

            // need to replace spaces in String before getting preferred width
            if (longValues[i] instanceof String) {
                longValues[i] = ((String)longValues[i]).replace(' ', '_');
            }

            System.out.println("longValues: " + longValues[i]);
            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                         getTableCellRendererComponent(
                             table, longValues[i],
                             false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            preferredWidth = Math.max(headerWidth, cellWidth);

            if (false) {
                System.out.println("Initializing width of column "
                    + i + ". "
                    + "preferredWidth = " + preferredWidth
                    + "; totalWidth = " + totalWidth
                    + "; leftWidth = " + (InstallWizard.DEFWIDTH - totalWidth));
            }

            //XXX: Before Swing 1.1 Beta 2, use setMinWidth instead.
            if (i == 2) {
                if (preferredWidth > InstallWizard.DEFWIDTH - totalWidth)
                    column.setPreferredWidth(InstallWizard.DEFWIDTH - totalWidth);
                else
                    column.setPreferredWidth(preferredWidth);
            }
            else {
                column.setMinWidth(preferredWidth);
                totalWidth += preferredWidth;
            }
        }
    } 

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField jTextField2;
	private InstallWizard wizard;
	private MyTableModelIDE  tableModel;
	private NavPanel nav;
    // End of variables declaration//GEN-END:variables
          
  }

class MyTableModelIDE extends AbstractTableModel {
    ArrayList data;
    String colNames[] = {"", "IDE Name", "IDE Location"};
    Object[] longValues = new Object[] {Boolean.TRUE, "Name", "Location"};
    
    MyTableModelIDE (Properties properties, String [] validVersions) {
        data = new ArrayList();
        //System.out.println(properties);
        
        int len = validVersions.length;
        for (int i = 0; i < len; i++) {
            String key = validVersions[i];
            String path = null;
            
            if ((path = properties.getProperty(key)) != null) {
                ArrayList row = new ArrayList();
                row.add(0, new Boolean(false));

                row.add(1, key);
                if (key.length() > ((String)longValues[1]).length()) {
                    longValues[1] = key;
                }

                row.add(2, path);
                if (path.length() > ((String)longValues[2]).length()) {
                    longValues[2] = path;
                }

                data.add(row);
            }
        }
    }// MyTableModel
    
    public int getColumnCount() {
        return 3;
    }
    
    public int getRowCount() {
        return data.size();
    }
    
    public String getColumnName(int col) {
        return colNames[col];
    }
    
    public Object getValueAt(int row, int col) {
        if (row < 0 || row > getRowCount() ||
            col < 0 || col > getColumnCount())
            return null;

        ArrayList aRow = (ArrayList)data.get(row);
        return aRow.get(col);
    }
    
	    public Class getColumnClass(int c) {
		return getValueAt(0, c).getClass();
	    }
	    
	    public boolean isCellEditable(int row, int col) {
		if (col == 0) {
		    return true;
		} else {
		    return false;
		}
	    }
	    
	    public void setValueAt(Object value, int row, int col) {
		ArrayList aRow = (ArrayList)data.get(row);
		aRow.set(col, value);
		fireTableCellUpdated(row, col);
	    }
	    
	    String [] getSelected() {
		return null;
	    }
	    
	    public boolean isAnySelected() {
		Iterator iter = data.iterator();
		while (iter.hasNext()) {
		    ArrayList row = (ArrayList)iter.next();
		    if (((Boolean)row.get(0)).booleanValue() == true) {
			return true;
		    }
		}
		return false;
	    }
	    
}

