/*
 * Copyright (C) 1999-2006 <a href="mailto:adrian.paschke@gmx.de">Adrian Paschke</a>
 * 
 * The RBSLM Environment is part of the Rule Based Service Level Agreement (RBSLA)
 * framework, available at 
 * <a href=" http://ibis.in.tum.de/staff/paschke/rbsla/index.htm">RBSLA</a>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package rbsla.environment.dialogs;

import java.awt.Button;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.TreeMap;
import java.util.Vector;

import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;

import org.apache.log4j.Logger;

import rbsla.wrapper.ProvaWrapper;
import rbsla.environment.ECAConstraints;
import rbsla.environment.ECAPanel;
import rbsla.environment.ECAWindow;
import rbsla.environment.StartViewDaemon;
import rbsla.environment.view.ViewDialog;
import rbsla.environment.view.ViewModell;
import rbsla.environment.view.Viewer;
import rbsla.environment.view.ViewerArray;

public class AddViewDialog extends JDialog implements ActionListener,
        KeyListener, WindowListener
{

    private Frame parentFrame;

    protected GridBagLayout myLayout;

    protected Button okButton;

    protected Button cancelButton;

    protected JTextField setTitelTextField;

    protected JTextField setValueTextField;

    protected JTextField setIntervalTextField;

    protected JLabel setDialogLabel;

    protected JLabel setTitelLabel;

    protected JLabel setValueLabel;

    protected JLabel setViewLabel;

    protected JLabel setViewerPropsLabel;

    protected JComboBox setViewComboBox;

    protected JTable viewerPropsTable;

    protected JTextArea textArea;

    private ProvaWrapper prova;

    private ViewModell viewModell;
    
    private ViewDialog viewDialog;

    private boolean createViewer = false;
    
    private PropertyTable propertyTable = new PropertyTable();

    private static Logger logger = Logger.getLogger(AddViewDialog.class);

    public AddViewDialog(Frame parent)
    {
        this(parent, new ViewModell(), "Add a new viewer");
    }

    public AddViewDialog(Frame parent, ViewDialog _viewDialog)
    {
        this(parent, _viewDialog.getViewModell(), "Change viewer");
        viewDialog = _viewDialog; 
    }

    private AddViewDialog(Frame parent, ViewModell _viewModell, String titel)
    {
        super(parent, titel, false);

        viewModell = _viewModell;
        parentFrame = parent;

        if (titel.equals("Add a new viewer"))
            createViewer = true;

        panelInit();
    }

    private void panelInit()
    {
        myLayout = new GridBagLayout();
        this.getContentPane().setLayout(myLayout);

        //set viewer titel
        setTitelLabel = new JLabel();
        setTitelLabel.setText("Title der Fenster");
        getContentPane().add(
                setTitelLabel,
                new ECAConstraints(1, 1, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));

        setTitelTextField = new JTextField();
        setTitelTextField.setText("");
        setTitelTextField.setDragEnabled(true);
        
        getContentPane().add(
                setTitelTextField,
                new ECAConstraints(3, 1, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));
        // value
        setValueLabel = new JLabel();
        setValueLabel.setText("Value");
        getContentPane().add(
                setValueLabel,
                new ECAConstraints(1, 2, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));

        setValueTextField = new JTextField();
        setValueTextField.setDragEnabled(true);
        
        getContentPane().add(
                setValueTextField,
                new ECAConstraints(3, 2, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));
        // viewer
        setViewLabel = new JLabel();
        setViewLabel.setText("Viewer");
        getContentPane().add(
                setViewLabel,
                new ECAConstraints(1, 3, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));

        setViewComboBox = new JComboBox();

        Vector viewers = ViewerArray.instance().getViewers();

        for (int i = 0; i < viewers.size(); i++)
            setViewComboBox.addItem((String) viewers.get(i));

        //setViewComboBox.setActionCommand("comboBoxChanged");
        getContentPane().add(
                setViewComboBox,
                new ECAConstraints(3, 3, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));

        // viewer can only be changed in the "add" mode
        if (createViewer)
        {
            setViewComboBox.addItemListener(new ItemListener()
            {
                public void itemStateChanged(ItemEvent e)
                {
                    JComboBox selectedChoice = (JComboBox) e.getSource();
                    showDefaultViewerProperties(selectedChoice);
                }
            });
        } else
        {
            setViewComboBox.setEnabled(false);
        }
        
        // viewer properties
        setViewerPropsLabel = new JLabel();
        setViewerPropsLabel.setText("Viewer properties");
        getContentPane().add(
                setViewerPropsLabel,
                new ECAConstraints(1, 4, 1, 1, 1.0, 1.0,
                        GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH,
                        new Insets(0, 0, 5, 0), 0, 0));



        viewerPropsTable = new JTable(propertyTable);
        viewerPropsTable.setPreferredScrollableViewportSize(new Dimension(450, 150));
        JScrollPane scrollpane = new JScrollPane(viewerPropsTable,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        //scrollpane.setSize(100,80);
        getContentPane().add(
                scrollpane,
                new ECAConstraints(3, 4, 1, 1, 1.0, 1.0,
                        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                        new Insets(0, 0, 0, 0), 0, 0));

        okButton = new Button("Ok");
        okButton.addActionListener(this);
        getContentPane().add(
                okButton,
                new ECAConstraints(5, 6, 1, 1, 1.0, 1.0,
                        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                        new Insets(0, 0, 0, 0), 0, 0));

        cancelButton = new Button("Cancel");
        cancelButton.addActionListener(this);
        getContentPane().add(
                cancelButton,
                new ECAConstraints(5, 7, 1, 1, 1.0, 1.0,
                        GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
                        new Insets(0, 0, 0, 0), 0, 0));

        // getContentPane().setSize(20, 40);

        pack();

        if (parentFrame instanceof ECAWindow)
            ECAPanel.centerDialog(parentFrame, this);
        else
            ECAPanel.centerDialogOnScreen(this);

        getContentPane().addKeyListener(this);
        addWindowListener(this);
        setResizable(true);
        if (!createViewer)
            setValues();

        setVisible(true);
    }

    private void setValues()
    {
        setValueTextField.setText(viewModell.getQuery());
        setTitelTextField.setText(viewModell.getViewTitel());
        // TODO: Das geht irgendwie noch nicht!
        setViewComboBox.setSelectedItem(viewModell.getViewerClassName());
        showViewerProperties(viewModell.getViewerProperties());
    }

    private void showViewerProperties(Hashtable getThisViewerProps)
    {
        propertyTable.changeValue(getThisViewerProps);
    }

    private void showDefaultViewerProperties(JComboBox selectedChoice)
    {
        try
        {
            Viewer currentViewer = (Viewer) Class.forName(
                    (String) selectedChoice.getSelectedItem()).newInstance();
            Hashtable getThisViewerProps = (Hashtable) currentViewer
                    .getViewerPropertieNames();
            if (getThisViewerProps == null)
                getThisViewerProps = new Hashtable();
            showViewerProperties(getThisViewerProps);
        } catch (Exception ex)
        {
            logger.info("", ex);

        }

    }

    private void setViewerPropertiesInModell()
    {

        Hashtable getThisViewerProps = new Hashtable();

        //Object[] keyList = (Object[]) getThisViewerProps.keySet().toArray();

        // set value
        for (int i = 0; i < viewerPropsTable.getRowCount(); i++)
        {
            getThisViewerProps.put(viewerPropsTable.getValueAt(i, 0),
                    viewerPropsTable.getValueAt(i, 1));
        }

        viewModell.setViewerProperties(getThisViewerProps);

    }

    public void actionPerformed(ActionEvent E)
    {
        if (E.getSource() == okButton)
        {
            String textViewStr = (String) setViewComboBox.getSelectedItem();

            if(textViewStr.equals("rbsla.environment.view.ActiveRulesViewer"))
            {
            	setValueTextField.setText("eca(TIME, EVENT, COND, ACTION, POSTCOND, ELSEACTION)");
            }
            
            try
            {
                viewModell.setQuery(setValueTextField.getText());
                String titelText = setTitelTextField.getText();
                if (titelText.equals(""))
                    titelText = setValueTextField.getText();
                viewModell.setViewTitel(titelText);
                if (createViewer)
                    viewModell.setViewerClassName((String) setViewComboBox
                        .getSelectedItem());
                setViewerPropertiesInModell();

                if (!createViewer)
                    viewDialog.dispose();
                
                StartViewDaemon.getInstance().addView(viewModell, parentFrame);

            } catch (Exception ex)
            {
                logger.info("", ex);
            }
            dispose();
        }

        else if (E.getSource() == cancelButton)
        {
            dispose();
        }
    }

    public void keyPressed(KeyEvent E)
    {
    }

    public void keyReleased(KeyEvent E)
    {

        if (E.getKeyCode() == E.VK_ENTER)
        {

        }

        if (E.getKeyCode() == E.VK_TAB)
        {

        }
    }

    public void keyTyped(KeyEvent E)
    {
    }

    public void windowActivated(WindowEvent E)
    {
    }

    public void windowClosed(WindowEvent E)
    {
    }

    public void windowClosing(WindowEvent E)
    {
        dispose();
    }

    public void windowDeactivated(WindowEvent E)
    {
    }

    public void windowDeiconified(WindowEvent E)
    {
    }

    public void windowIconified(WindowEvent E)
    {
    }

    public void windowOpened(WindowEvent E)
    {
    }

}


class PropertyTable extends AbstractTableModel
{   
    TreeMap sortedMap = new TreeMap();
    ArrayList arrayList = new ArrayList();
    
    
    public PropertyTable()
    {
        Hashtable hash = new Hashtable();
        changeValue(hash);
    }
    
    public void changeValue(Hashtable hastable)
    {
        sortedMap = new TreeMap(hastable);
        arrayList = new ArrayList(sortedMap.keySet());
        fireTableStructureChanged();
        fireTableDataChanged();
        
    }
    
    /**
     * Returns the number of rows in the model. A
     * <code>JTable</code> uses this method to determine how many rows it
     * should display.  This method should be quick, as it
     * is called frequently during rendering.
     *
     * @return the number of rows in the model
     * @see #getColumnCount
     */
    public int getRowCount()
    {
        return sortedMap.size();
    }

    /**
     * Returns the number of columns in the model. A
     * <code>JTable</code> uses this method to determine how many columns it
     * should create and display by default.
     *
     * @return the number of columns in the model
     * @see #getRowCount
     */
    public int getColumnCount()
    {
        return 2;
    }

    /**
     * Returns the name of the column at <code>columnIndex</code>.  This is used
     * to initialize the table's column header name.  Note: this name does
     * not need to be unique; two columns in a table can have the same name.
     *
     * @param	columnIndex	the index of the column
     * @return  the name of the column
     */
    public String getColumnName(int columnIndex)
    {
        if (columnIndex==0)
            return "Property";
        else
            return "Value";
    }

    /**
     * Returns the most specific superclass for all the cell values 
     * in the column.  This is used by the <code>JTable</code> to set up a 
     * default renderer and editor for the column.
     *
     * @param columnIndex  the index of the column
     * @return the common ancestor class of the object values in the model.
     */
    public Class getColumnClass(int columnIndex)
    {
        return String.class;
    }

    /**
     * Returns true if the cell at <code>rowIndex</code> and
     * <code>columnIndex</code>
     * is editable.  Otherwise, <code>setValueAt</code> on the cell will not
     * change the value of that cell.
     *
     * @param	rowIndex	the row whose value to be queried
     * @param	columnIndex	the column whose value to be queried
     * @return	true if the cell is editable
     * @see #setValueAt
     */
    public boolean isCellEditable(int rowIndex, int columnIndex)
    {
        if (columnIndex==1)
            return true;
        else 
            return false;
    }

    /**
     * Returns the value for the cell at <code>columnIndex</code> and
     * <code>rowIndex</code>.
     *
     * @param	rowIndex	the row whose value is to be queried
     * @param	columnIndex 	the column whose value is to be queried
     * @return	the value Object at the specified cell
     */
    public Object getValueAt(int rowIndex, int columnIndex)
    {
        if (columnIndex==0)
            return arrayList.get(rowIndex);
        else
            return sortedMap.get(arrayList.get(rowIndex));
    }

    /**
     * Sets the value in the cell at <code>columnIndex</code> and
     * <code>rowIndex</code> to <code>aValue</code>.
     *
     * @param	aValue		 the new value
     * @param	rowIndex	 the row whose value is to be changed
     * @param	columnIndex 	 the column whose value is to be changed
     * @see #getValueAt
     * @see #isCellEditable
     */
    public void setValueAt(Object aValue, int rowIndex, int columnIndex)
    {
        Object key = arrayList.get(rowIndex);
        Object value = sortedMap.get(arrayList.get(rowIndex));
        sortedMap.remove(key);
        
        if (columnIndex==0)
            key = aValue;
        else
            value = aValue;
        
        sortedMap.put(key,value);
        arrayList = new ArrayList(sortedMap.keySet());
        fireTableDataChanged();
    }

    /**
     * Adds a listener to the list that is notified each time a change
     * to the data model occurs.
     *
     * @param	l		the TableModelListener
     */

}

