/*
 * 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 org.apache.log4j.chainsaw.receivers;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractCellEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;

import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.chainsaw.ChainsawConstants;
import org.apache.log4j.chainsaw.Generator;
import org.apache.log4j.chainsaw.helper.TableCellEditorFactory;
import org.apache.log4j.net.SocketHubReceiver;
import org.apache.log4j.plugins.Plugin;


/**
 * A panel that allows the user to edit a particular Plugin, by using introspection
 * this class discovers the modifiable properties of the Plugin
 * @author Paul Smith &lt;psmith@apache.org&gt;
 */
public class PluginPropertyEditorPanel extends JPanel {

    private final JScrollPane scrollPane = new JScrollPane();
    private final JTable propertyTable = new JTable();

    private Plugin plugin;
    private TableModel defaultModel = new DefaultTableModel(
            new String[] { "Property", "Value" }, 1);

    private static final Logger logger = LogManager.getLogger(PluginPropertyEditorPanel.class);
    /**
     *
     */
    public PluginPropertyEditorPanel() {
        super();
        initComponents();
        setupListeners();
    }

    /**
     *
     */
    private void initComponents() {
        propertyTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
        setLayout(new BorderLayout());
        scrollPane.setViewportView(propertyTable);

        add(scrollPane, BorderLayout.CENTER);

        propertyTable.setModel(
            defaultModel = new DefaultTableModel(
                    new String[] { "Property", "Value" }, 1));

    }

    /**
     *
     */
    private void setupListeners() {
        addPropertyChangeListener("plugin", new PropertyChangeListener() {

                public void propertyChange(PropertyChangeEvent evt) {

                    final Plugin p = (Plugin) evt.getNewValue();

                    if (p != null) {

                        try {

                            PluginPropertyTableModel model =
                                new PluginPropertyTableModel(p);
                            propertyTable.setModel(model);
                            propertyTable.getColumnModel().getColumn(1)
                            .setCellEditor(new PluginTableCellEditor());
                            propertyTable.setEnabled(true);
                        } catch (Throwable e) {
                            logger.error("Failed to introspect the Plugin", e);
                        }
                    } else {
                        propertyTable.setModel(defaultModel);
                        propertyTable.setEnabled(false);
                    }

                }
            });
    }

    public static void main(String[] args) {

        JFrame frame = new JFrame("Property Editor Test bed");
        frame.addWindowListener(new WindowAdapter() {
                public void windowClosed(WindowEvent e) {
                    System.exit(1);
                }
            });

        PluginPropertyEditorPanel panel = new PluginPropertyEditorPanel();


        frame.getContentPane().add(panel);
        frame.pack();

        frame.setVisible(true);

        SocketHubReceiver r = new SocketHubReceiver();

        panel.setPlugin(r);

        try {
            Thread.sleep(3000);

            panel.setPlugin(new Generator("MyPlugin"));
        } catch (Exception e) {
            // TODO: handle exception
        }


    }

    /**
     * @return Returns the plugin.
     */
    public final Plugin getPlugin() {

        return plugin;
    }

    /**
     * @param plugin The plugin to set.
     */
    public final void setPlugin(Plugin plugin) {

        Plugin oldValue = this.plugin;
        this.plugin = plugin;
        firePropertyChange("plugin", oldValue, this.plugin);
    }

    /**
     * @author psmith
     *
     */
    private class PluginTableCellEditor extends AbstractCellEditor
        implements TableCellEditor {

        private Map editorMap = new HashMap();
        private DefaultCellEditor defaultEditor = new DefaultCellEditor(
                new JTextField());
        private DefaultCellEditor currentEditor = defaultEditor;

        private PluginTableCellEditor() {

            editorMap.put(Boolean.class,
                TableCellEditorFactory.createBooleanTableCellEditor());
            editorMap.put(Level.class,
                TableCellEditorFactory.createLevelTableCellEditor());
            //support primitive boolean parameters with the appropriate editor
            editorMap.put(boolean.class, TableCellEditorFactory.createBooleanTableCellEditor());
        }

        /* (non-Javadoc)
         * @see javax.swing.table.TableCellEditor#getTableCellEditorComponent(javax.swing.JTable, java.lang.Object, boolean, int, int)
         */
        public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {

           PluginPropertyTableModel model = (PluginPropertyTableModel) table.getModel();
           PropertyDescriptor descriptor =  model.getDescriptors()[row];
           Class valueClass = descriptor.getPropertyType();
           
            if (editorMap.containsKey(valueClass)) {

                DefaultCellEditor editor =
                    (DefaultCellEditor) editorMap.get(valueClass);
                logger.debug("Located CellEditor for " + valueClass);
                currentEditor = editor;

                return currentEditor.getTableCellEditorComponent(table, value,
                    isSelected, row, column);
            }

            currentEditor = defaultEditor;
            logger.debug("Cell value class " + valueClass +
                " not know, using default editor");

            return defaultEditor.getTableCellEditorComponent(table, value,
                isSelected, row, column);
        }

        /* (non-Javadoc)
         * @see javax.swing.CellEditor#getCellEditorValue()
         */
        public Object getCellEditorValue() {

            return currentEditor.getCellEditorValue();
        }

    }

    private static class PluginPropertyTableModel extends AbstractTableModel {

        private final PropertyDescriptor[] descriptors;
        private final Plugin plugin;

        private PluginPropertyTableModel(Plugin p)
            throws IntrospectionException {
            super();

            BeanInfo beanInfo = Introspector.getBeanInfo(p.getClass());

            List list = new ArrayList(Arrays.asList(
                        beanInfo.getPropertyDescriptors()));

            Collections.sort(list, new Comparator() {

                    public int compare(Object o1, Object o2) {

                        PropertyDescriptor d1 = (PropertyDescriptor) o1;
                        PropertyDescriptor d2 = (PropertyDescriptor) o2;

                        return d1.getDisplayName().compareToIgnoreCase(
                            d2.getDisplayName());
                    }
                });
            this.plugin = p;
            this.descriptors = (PropertyDescriptor[]) list.toArray(
                    new PropertyDescriptor[0]);
        }

        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#getValueAt(int, int)
         */
        public Object getValueAt(int row, int col) {

            PropertyDescriptor d = descriptors[row];

            switch (col) {

            case 1:

                try {

                    Object object = d.getReadMethod().invoke(plugin,
                            new Object[0]);

                    if (object != null) {

                        return object;
                    }
                } catch (Exception e) {
                    logger.error(
                        "Error reading value for PropertyDescriptor " + d);
                }

                return "";

            case 0:
                return d.getName();
            }

            return null;
        }

        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#getColumnCount()
         */
        public int getColumnCount() {

            return 2;
        }

        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#getRowCount()
         */
        public int getRowCount() {

            return descriptors.length;
        }

        /* (non-Javadoc)
         * @see javax.swing.table.TableModel#isCellEditable(int, int)
         */
        public boolean isCellEditable(int rowIndex, int columnIndex) {

//        TODO Determine if the property is one of the ones a User could edit
            if (columnIndex == 1) {

                return descriptors[rowIndex].getWriteMethod() != null;
            }

            return false;
        }

        /* (non-Javadoc)
         * @see javax.swing.table.TableModel#getColumnName(int)
         */
        public String getColumnName(int column) {

            return (column == 0) ? "Property" : "Value";
        }

        /* (non-Javadoc)
         * @see javax.swing.table.TableModel#setValueAt(java.lang.Object, int, int)
         */
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {


            if (columnIndex == 1) {
                //ensure name is set
                if (descriptors[rowIndex].getName().equalsIgnoreCase("name") && (aValue == null || aValue.toString().trim().equals(""))) {
                    logger.error("Name required");
                    return;
                }
                aValue = translateValueIfNeeded(rowIndex, aValue);
                logger.debug(
                    "setValueAt, " + rowIndex + ", " + columnIndex +
                    ", value=" + aValue + ", valueClass" + aValue.getClass());

                try {
                    descriptors[rowIndex].getWriteMethod().invoke(plugin,
                        new Object[] { aValue });
                    fireTableCellUpdated(rowIndex, columnIndex);
                } catch (IllegalArgumentException e) {
                    // ignore
                } catch (Exception e) {
                    logger.error(
                        "Failed to modify the Plugin because of Exception", e);
                }

            } else {
                super.setValueAt(aValue, rowIndex, columnIndex);
            }
        }

        /**
         * @param row
         * @param value
         * @return
         */
        private Object translateValueIfNeeded(int row, Object value) {

            if ((descriptors[row].getPropertyType() == int.class) ||
                    (descriptors[row].getPropertyType() == Integer.class)) {

                try {

                    return Integer.valueOf(value.toString());
                } catch (Exception e) {
                    logger.error("Failed to convert to Integer type");
                }
            }

            return value;
        }
        /**
         * @return Returns the descriptors.
         */
        public final PropertyDescriptor[] getDescriptors() {
          return descriptors;
        }
    }
}
