/*
 * iReport - Visual Designer for JasperReports.
 * Copyright (C) 2002 - 2009 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of iReport.
 *
 * iReport is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * iReport 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with iReport. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.ireport.designer.options.jasperreports;

import com.jaspersoft.ireport.designer.IReportManager;
import com.jaspersoft.ireport.designer.options.IReportOptionsPanelController;
import com.jaspersoft.ireport.designer.options.OptionsPanel;

import com.jaspersoft.ireport.designer.utils.Misc;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import net.sf.jasperreports.engine.util.JRProperties;
import net.sf.jasperreports.engine.util.JRProperties.PropertySuffix;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.SortOrder;

/**
 *
 * @author gtoffoli
 */
public class JROptionsPanel extends javax.swing.JPanel implements OptionsPanel{

    
    IReportOptionsPanelController controller = null;
    private boolean init = false;

    public boolean setInit(boolean b)
    {
        boolean old = init;
        init =b;
        return old;
    }

    public boolean getInit()
    {
        return init;
    }


    /** Creates new form ExportOptionsPanel */
    public JROptionsPanel(IReportOptionsPanelController controller) {
        initComponents();
        this.controller = controller;

        jTable1.getSelectionModel().addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                jButtonRemove.setEnabled(jTable1.getSelectedRowCount() > 0);
                jButtonRestoreDefault.setEnabled(jTable1.getSelectedRowCount() > 0);
                jButtonModify.setEnabled(jTable1.getSelectedRowCount() > 0);
            }
        });

        ((DefaultTableModel)jTable1.getModel()).addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {
               notifyChange();
            }
        });

        JRPropertyTableCellRenderer cr = new JRPropertyTableCellRenderer();
        jTable1.getColumnModel().getColumn(0).setCellRenderer(cr);
        jTable1.getColumnModel().getColumn(1).setCellRenderer(cr);

        ((JXTable)jTable1).setColumnControlVisible(true);
        ((JXTable)jTable1).setSortOrder(0, SortOrder.ASCENDING);
        
    }

    public void notifyChange()
    {
        if (getInit()) return;
        if (controller != null) controller.changed();
    }

    /** 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.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new org.jdesktop.swingx.JXTable();
        jPanel1 = new javax.swing.JPanel();
        jButtonAddProperty = new javax.swing.JButton();
        jButtonRemove = new javax.swing.JButton();
        jButtonRestoreDefault = new javax.swing.JButton();
        jButtonModify = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();

        setLayout(new java.awt.BorderLayout());

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Value"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, true
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTable1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTable1MouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(jTable1);
        jTable1.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jTable1.columnModel.title0")); // NOI18N
        jTable1.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jTable1.columnModel.title1")); // NOI18N

        add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jButtonAddProperty.setText(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jButtonAddProperty.text")); // NOI18N
        jButtonAddProperty.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAddPropertyActionPerformed(evt);
            }
        });

        jButtonRemove.setText(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jButtonRemove.text")); // NOI18N
        jButtonRemove.setEnabled(false);
        jButtonRemove.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonRemoveActionPerformed(evt);
            }
        });

        jButtonRestoreDefault.setText(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jButtonRestoreDefault.text")); // NOI18N
        jButtonRestoreDefault.setEnabled(false);
        jButtonRestoreDefault.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonRestoreDefaultActionPerformed(evt);
            }
        });

        jButtonModify.setText(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jButtonModify.text")); // NOI18N
        jButtonModify.setEnabled(false);
        jButtonModify.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonModifyActionPerformed(evt);
            }
        });

        jLabel1.setText(org.openide.util.NbBundle.getMessage(JROptionsPanel.class, "JROptionsPanel.jLabel1.text")); // NOI18N

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(10, 10, 10)
                        .add(jLabel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 558, Short.MAX_VALUE))
                    .add(jPanel1Layout.createSequentialGroup()
                        .addContainerGap()
                        .add(jButtonAddProperty, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 112, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButtonModify)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButtonRemove)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButtonRestoreDefault)))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jButtonAddProperty)
                    .add(jButtonModify)
                    .add(jButtonRemove)
                    .add(jButtonRestoreDefault))
                .add(18, 18, 18)
                .add(jLabel1)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        add(jPanel1, java.awt.BorderLayout.PAGE_END);
    }// </editor-fold>//GEN-END:initComponents

    private void jButtonRemoveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonRemoveActionPerformed

        int[] selectedRows = jTable1.getSelectedRows();
        Arrays.sort(selectedRows);


        for (int i=selectedRows.length-1; i>=0; --i)
        {
            int modelIndex = ((JXTable)jTable1).convertRowIndexToModel(selectedRows[i]);

            String key = (String)((DefaultTableModel)jTable1.getModel()).getValueAt(modelIndex, 0);

            if (IReportManager.getInstance().getDefaultJasperReportsProperties().containsKey(key))
            {
                JOptionPane.showMessageDialog(this, "The property \n" + key + "\ncan not be deleted since it is set by default by JasperReports.", "System property",JOptionPane.INFORMATION_MESSAGE );
            }
            else
            {

                ((DefaultTableModel)jTable1.getModel()).removeRow(modelIndex);
                notifyChange();
            }
        }
        jTable1.updateUI();


    }//GEN-LAST:event_jButtonRemoveActionPerformed

    private void jButtonAddPropertyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAddPropertyActionPerformed

        JRPropertyDialog pd = new JRPropertyDialog(Misc.getMainFrame(), true);
        // Get all the names...
        DefaultTableModel dtm = (DefaultTableModel) jTable1.getModel();
        List<String> usedKeys = new ArrayList<String>();

        for (int i=0; i<dtm.getRowCount(); ++i)
        {
            String key = (String) dtm.getValueAt(i, 0);
            usedKeys.add(key);
        }
        pd.setExistingPropertiesNames(usedKeys);

        pd.setVisible(true);

        if (pd.getDialogResult() == JOptionPane.OK_OPTION)
        {
            dtm.addRow(new Object[]{pd.getPropertyName(), pd.getPropertyValue()});

            int newIndex = ((JXTable)jTable1).convertRowIndexToView(dtm.getRowCount()-1);
            jTable1.getSelectionModel().setSelectionInterval(newIndex, newIndex);
            Rectangle rect =  jTable1.getCellRect(newIndex, 0, true);
            jTable1.scrollRectToVisible(rect);
            notifyChange();
        }

    }//GEN-LAST:event_jButtonAddPropertyActionPerformed

    private void jButtonRestoreDefaultActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonRestoreDefaultActionPerformed

        int[] selectedRows = jTable1.getSelectedRows();
        Arrays.sort(selectedRows);
        DefaultTableModel dtm = (DefaultTableModel) jTable1.getModel();
        for (int i=selectedRows.length-1; i>=0; --i)
        {
            int modelIndex = ((JXTable)jTable1).convertRowIndexToModel(selectedRows[i]);
            String key = (String)((DefaultTableModel)jTable1.getModel()).getValueAt(modelIndex, 0);
            if (IReportManager.getInstance().getDefaultJasperReportsProperties().containsKey(key))
            {
                String def = IReportManager.getInstance().getDefaultJasperReportsProperties().getProperty(key);
                dtm.setValueAt(Misc.addSlashesString(def), modelIndex, 1);
            }
        }
        jTable1.updateUI();

}//GEN-LAST:event_jButtonRestoreDefaultActionPerformed

    private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTable1MouseClicked
        if (evt.getClickCount() == 2 && SwingUtilities.isLeftMouseButton(evt))
        {
            jButtonModifyActionPerformed(null);
        }
    }//GEN-LAST:event_jTable1MouseClicked

    private void jButtonModifyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonModifyActionPerformed
        if (jTable1.getSelectedRow() >= 0)
            {
                DefaultTableModel dtm = (DefaultTableModel) jTable1.getModel();

                int modelIndex = ((JXTable)jTable1).convertRowIndexToModel(jTable1.getSelectedRow());
                String keyProp = (String)dtm.getValueAt(modelIndex, 0);
                String valueProp = (String)dtm.getValueAt(modelIndex, 1);

                JRPropertyDialog pd = new JRPropertyDialog(Misc.getMainFrame(), true);
                List<String> usedKeys = new ArrayList<String>();

                for (int i=0; i<dtm.getRowCount(); ++i)
                {
                    String key = (String) dtm.getValueAt(i, 0);
                    usedKeys.add(key);
                }
                pd.setExistingPropertiesNames(usedKeys);
                pd.setPropertyName(keyProp);
                pd.setPropertyValue(valueProp);
                pd.setVisible(true);

                if (pd.getDialogResult() == JOptionPane.OK_OPTION)
                {
                    dtm.setValueAt(pd.getPropertyName(),modelIndex,0);
                    dtm.setValueAt(pd.getPropertyValue(),modelIndex,1);
                    jTable1.updateUI();
                }
            }
}//GEN-LAST:event_jButtonModifyActionPerformed

    public void load() {

        setInit(true);

        DefaultTableModel dtm = (DefaultTableModel) jTable1.getModel();
        dtm.setRowCount(0);

        Properties props = IReportManager.getInstance().getPersistentJRProperties();

        Enumeration propNames = props.propertyNames();

        while (propNames.hasMoreElements())
        {
            String propName = (String) propNames.nextElement();
            dtm.addRow(new Object[]{propName, Misc.addSlashesString(props.getProperty(propName) )});
        }

        jTable1.updateUI();

        setInit(false);

    }

    public void store() {

        DefaultTableModel dtm = (DefaultTableModel) jTable1.getModel();

        List<String> usedKeys = new ArrayList<String>();

        for (int i=0; i<dtm.getRowCount(); ++i)
        {
            String key = (String) dtm.getValueAt(i, 0);
            String value = (String) dtm.getValueAt(i, 1);

            usedKeys.add(key);

            if (IReportManager.getInstance().getDefaultJasperReportsProperties().containsKey(key))
            {
                String oldValue = JRProperties.getProperty(key);
                if (oldValue == null || !oldValue.equals(value))
                {
                    IReportManager.getPreferences().put(IReportManager.PROPERTY_JRPROPERTY_PREFIX + key, Misc.removeSlashesString(value));
                }
                else
                {
                    IReportManager.getPreferences().remove(IReportManager.PROPERTY_JRPROPERTY_PREFIX + key);
                }
            }
            else
            {
                
                IReportManager.getPreferences().put(IReportManager.PROPERTY_JRPROPERTY_PREFIX + key, Misc.removeSlashesString(value));
            }
        }

        // Check removed keys...
        List props = JRProperties.getProperties("");
        for (int i=0; i<props.size(); ++i)
        {
            String oldKey = ((PropertySuffix)props.get(i)).getKey();
            if (!usedKeys.contains(oldKey))
            {
                // This key has been removed...
                if (!IReportManager.getInstance().getDefaultJasperReportsProperties().containsKey(oldKey))
                {
                    // it is not a predefined property
                    // To remove this property a restart is suggested...
                    IReportManager.getPreferences().remove(IReportManager.PROPERTY_JRPROPERTY_PREFIX + oldKey);
                    JRProperties.removePropertyValue(oldKey);
                }
            }
        }
        
        IReportManager.getInstance().reloadJasperReportsProperties();
    }

    public boolean valid() {
        return true;
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonAddProperty;
    private javax.swing.JButton jButtonModify;
    private javax.swing.JButton jButtonRemove;
    private javax.swing.JButton jButtonRestoreDefault;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration//GEN-END:variables

}
