package com.dbxml.db.admin.dialogs;

/*
 * dbXML - Native XML Database
 * Copyright (C) 1999-2004  The dbXML Group, L.L.C.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Id: PreferencesDialog.java,v 1.11 2004/02/12 00:17:54 bradford Exp $
 */

import java.awt.*;
import javax.swing.*;

import com.dbxml.db.admin.Admin;
import com.dbxml.db.admin.AdminConfig;
import com.dbxml.db.admin.components.XSLTViewer;
import com.dbxml.db.admin.swing.JLabelListCellRenderer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * PreferencesDialog
 */

public final class PreferencesDialog extends JDialog {
   private static final String[] NSColumnNames = new String[]{"Prefix", "URI"};

   private AdminConfig config;

   private List nsMap = new ArrayList();
   private NSTableModel tblModel = new NSTableModel();

   ImageIcon imgQryBefore;
   ImageIcon imgQryAfter;
   ImageIcon imgQryRemove;
   ImageIcon imgQryAppend;
   ImageIcon imgQryUpdate;
   ImageIcon imgQryXPath;
   ImageIcon imgQryXSLT;

   ImageIcon imgHTMLView;
   ImageIcon imgXMLView;
   ImageIcon imgTextView;

   GridBagLayout thisLayout = new GridBagLayout();
   JPanel pnlButtons = new JPanel();
   JButton btnOK = new JButton();
   JButton btnCancel = new JButton();
   BorderLayout pnlButtonsLayout = new BorderLayout();
   JPanel pnlDialog = new JPanel();
   JTabbedPane tabsPreferences = new JTabbedPane();
   JPanel pnlGeneral = new JPanel();
   JPanel pnlEditing = new JPanel();
   TitledBorder borderEditing;
   GridBagLayout gridBagLayout1 = new GridBagLayout();
   JCheckBox chkAutoBeautify = new JCheckBox();
   GridBagLayout gridBagLayout2 = new GridBagLayout();
   JLabel lblDefaultXSLTView = new JLabel();
   JComboBox cmbDefaultXSLTView = new JComboBox();
   JPanel pnlUI = new JPanel();
   GridBagLayout gridBagLayout4 = new GridBagLayout();
   TitledBorder borderUI;
   JLabel lblDefaultQueryType = new JLabel();
   JComboBox cmbDefaultQuery = new JComboBox();
   JPanel pnlQueries = new JPanel();
   GridBagLayout gridBagLayout3 = new GridBagLayout();
   JPanel pnlNS = new JPanel();
   TitledBorder borderNS;
   JScrollPane paneNS = new JScrollPane();
   JTable tblNS = new JTable();
   GridBagLayout gridBagLayout5 = new GridBagLayout();
   JPanel pnlNSButtons = new JPanel();
   JLabel lblNS = new JLabel();
   JButton btnNSRemove = new JButton();
   JButton btnNSAdd = new JButton();
   JPanel pnlSpacer1 = new JPanel();
   JPanel pnlSpacer2 = new JPanel();

   public PreferencesDialog(Frame owner) {
      super(owner, true);
      enableEvents(AWTEvent.WINDOW_EVENT_MASK);

      config = Admin.getInstance().getAdminConfig();

      Map ns = config.getNamespaceMap();
      Iterator iter = ns.entrySet().iterator();
      while ( iter.hasNext() ) {
         Map.Entry entry = (Map.Entry)iter.next();
         String prefix = (String)entry.getKey();
         String uri = (String)entry.getValue();
         nsMap.add(new NameValue(prefix, uri));
      }

      tblNS.setModel(tblModel);
      NSTableSelectionListener listener = new NSTableSelectionListener();
      tblNS.getSelectionModel().addListSelectionListener(listener);
      tblNS.getColumnModel().getSelectionModel().addListSelectionListener(listener);

      testRequired();

      try {
         jbInit();

         TableColumnModel tcm = tblNS.getColumnModel();
         TableColumn tc = tcm.getColumn(0);
         tc.setResizable(false);
         tc.setWidth(75);
         tc.setMinWidth(75);
         tc.setMaxWidth(75);

         cmbDefaultQuery.setRenderer(JLabelListCellRenderer.getInstance());
         cmbDefaultQuery.addItem(new JLabel("XPath (Select)", imgQryXPath, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("FullText (Search)", imgTextView, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XSLT (Transform)", imgQryXSLT, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XUpdate (Insert Before)", imgQryBefore, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XUpdate (Insert After)", imgQryAfter, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XUpdate (Append)", imgQryAppend, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XUpdate (Update)", imgQryUpdate, SwingConstants.LEFT));
         cmbDefaultQuery.addItem(new JLabel("XUpdate (Remove)", imgQryRemove, SwingConstants.LEFT));
         cmbDefaultQuery.setSelectedIndex(config.getDefaultQueryType(0));

         cmbDefaultXSLTView.setRenderer(JLabelListCellRenderer.getInstance());
         cmbDefaultXSLTView.addItem(new JLabel("text/html", imgHTMLView, SwingConstants.LEFT));
         cmbDefaultXSLTView.addItem(new JLabel("text/xml", imgXMLView, SwingConstants.LEFT));
         cmbDefaultXSLTView.addItem(new JLabel("text/plain", imgTextView, SwingConstants.LEFT));
         cmbDefaultXSLTView.setSelectedIndex(config.getDefaultXSLTView(0));

         chkAutoBeautify.setSelected(config.isAutoBeautify(false));

         pack();

         // Center the Dialog
         Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
         Dimension frameSize = getSize();
         if (frameSize.height > screenSize.height)
           frameSize.height = screenSize.height;
         if (frameSize.width > screenSize.width)
           frameSize.width = screenSize.width;
         setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
      }
      catch ( Exception e ) {
         Admin.getInstance().addMessage(e.toString());
      }
   }

   private void jbInit() throws Exception {
      imgQryBefore = new ImageIcon(Admin.class.getResource("insert_before.gif"));
      imgQryAfter = new ImageIcon(Admin.class.getResource("insert_after.gif"));
      imgQryRemove = new ImageIcon(Admin.class.getResource("delete.gif"));
      imgQryAppend = new ImageIcon(Admin.class.getResource("append.gif"));
      imgQryUpdate = new ImageIcon(Admin.class.getResource("update.gif"));
      imgQryXPath = new ImageIcon(Admin.class.getResource("xpath.gif"));
      imgQryXSLT = new ImageIcon(Admin.class.getResource("xslt.gif"));

      imgHTMLView = new ImageIcon(XSLTViewer.class.getResource("xslt_view.gif"));
      imgXMLView = new ImageIcon(XSLTViewer.class.getResource("text_view.gif"));
      imgTextView = new ImageIcon(XSLTViewer.class.getResource("plain_view.gif"));

      borderEditing = new TitledBorder(null, "Text Editing");
      borderUI = new TitledBorder(null, "User Interface");
      borderNS = new TitledBorder(null, "Namespaces");

      this.setModal(true);
      this.setResizable(false);
      this.setTitle("Administrator Preferences");
      pnlGeneral.setLayout(gridBagLayout1);
      pnlEditing.setBorder(borderEditing);
      pnlEditing.setLayout(gridBagLayout2);
      chkAutoBeautify.setText("Automatically Beautify XML");
      lblDefaultXSLTView.setText("Default XSLT View");
      pnlUI.setLayout(gridBagLayout4);
      pnlUI.setBorder(borderUI);
      lblDefaultQueryType.setToolTipText("");
      lblDefaultQueryType.setText("Default Query Type");
      pnlQueries.setLayout(gridBagLayout3);
      pnlNS.setBorder(borderNS);
      pnlNS.setLayout(gridBagLayout5);
      paneNS.setMinimumSize(new Dimension(250, 150));
      paneNS.setPreferredSize(new Dimension(250, 150));
      tblNS.setShowGrid(true);
      tblNS.setPreferredScrollableViewportSize(new Dimension(250, 150));
      tblNS.setAutoCreateColumnsFromModel(true);
      tblNS.setCellSelectionEnabled(false);
      tblNS.setColumnSelectionAllowed(false);
      tblNS.setRowSelectionAllowed(false);
      tblNS.setEditingColumn(0);

      lblNS.setText("Prefix Map");

      btnNSRemove.setFont(new java.awt.Font("Dialog", 0, 12));
      btnNSRemove.setText("Remove");
      btnNSRemove.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnNSRemove_actionPerformed(e);
         }
      });
      btnNSAdd.setFont(new java.awt.Font("Dialog", 0, 12));
      btnNSAdd.setText("Add");
      btnNSAdd.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnNSAdd_actionPerformed(e);
         }
      });

      this.getContentPane().add(pnlDialog);
      pnlDialog.setLayout(thisLayout);

      pnlButtons.setLayout(pnlButtonsLayout);
      btnOK.setFont(new java.awt.Font("Dialog", 0, 12));
      btnOK.setActionCommand("connect");
      btnOK.setSelected(true);
      btnOK.setText("ok");
      btnOK.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnOK_actionPerformed(e);
         }
      });
      btnCancel.setFont(new Font("Dialog", 0, 12));
      btnCancel.setActionCommand("cancel");
      btnCancel.setText("cancel");
      btnCancel.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnCancel_actionPerformed(e);
         }
      });

      pnlButtonsLayout.setHgap(5);
      pnlDialog.add(pnlButtons,  new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 10, 10, 10), 0, 0));
      pnlButtons.add(btnOK, BorderLayout.CENTER);
      pnlButtons.add(btnCancel,  BorderLayout.EAST);
      pnlDialog.add(tabsPreferences,    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 20, 10), 0, 0));
      tabsPreferences.add(pnlGeneral,  "General");
      pnlGeneral.add(pnlEditing,         new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 10), 59, 0));
      pnlEditing.add(chkAutoBeautify,  new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(10, 10, 10, 10), 0, 0));
      pnlGeneral.add(pnlUI,       new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 10), 0, 0));
      pnlUI.add(lblDefaultQueryType,       new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
      pnlUI.add(cmbDefaultQuery,   new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 0, 10, 10), 0, 0));
      pnlUI.add(lblDefaultXSLTView,   new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 10, 10, 10), 0, 0));
      pnlUI.add(cmbDefaultXSLTView,    new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 10), 0, 0));
      pnlGeneral.add(pnlSpacer1,     new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
      tabsPreferences.add(pnlQueries,   "Queries");
      pnlQueries.add(pnlNS,     new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0));
      pnlNS.add(paneNS,        new GridBagConstraints(1, 0, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(10, 10, 0, 10), 0, 0));
      paneNS.getViewport().add(tblNS, null);
      pnlNS.add(pnlNSButtons,   new GridBagConstraints(0, 1, 2, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 10, 10, 10), 0, 0));
      pnlNS.add(lblNS,    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 0), 0, 0));
      pnlNSButtons.add(btnNSAdd, null);
      pnlNSButtons.add(btnNSRemove, null);
      pnlQueries.add(pnlSpacer2,   new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
   }

   protected void processWindowEvent(WindowEvent e) {
      super.processWindowEvent(e);
      if ( e.getID() == WindowEvent.WINDOW_CLOSING ) {
         hide();
      }
   }

   void btnNSAdd_actionPerformed(ActionEvent e) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            nsMap.add(new NameValue());
            int row = nsMap.size()-1;

            tblModel.fireTableRowsInserted(row, row);

            tblNS.grabFocus();
            tblNS.getSelectionModel().clearSelection();
            tblNS.getColumnModel().getSelectionModel().clearSelection();
            tblNS.getSelectionModel().setSelectionInterval(row, row);
            tblNS.getColumnModel().getSelectionModel().setSelectionInterval(0, 0);
            tblNS.editCellAt(row, 0);

            btnNSRemove.setEnabled(true);
         }
      });
   }

   void btnNSRemove_actionPerformed(ActionEvent e) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            int row = tblNS.getSelectedRow();
            if ( row != -1 ) {
               CellEditor ce = tblNS.getCellEditor();
               if ( ce != null )
                  ce.stopCellEditing();

               tblNS.grabFocus();
               nsMap.remove(row);
               tblNS.getSelectionModel().clearSelection();
               tblNS.getColumnModel().getSelectionModel().clearSelection();
               tblModel.fireTableRowsDeleted(row, row);
            }
         }
      });
   }

   void btnOK_actionPerformed(ActionEvent e) {
      try {
         config.setAutoBeautify(chkAutoBeautify.isSelected());
         config.setDefaultQueryType(cmbDefaultQuery.getSelectedIndex());
         config.setDefaultXSLTView(cmbDefaultXSLTView.getSelectedIndex());

         Map newMap = new TreeMap();
         Iterator iter = nsMap.iterator();
         while ( iter.hasNext() ) {
            NameValue nv = (NameValue)iter.next();
            newMap.put(nv.name, nv.value);
         }
         config.setNamespaceMap(newMap);

         config.save();
         hide();
      }
      catch ( Exception ex ) {
         Admin.getInstance().addMessage(ex.getMessage());
      }
   }

   void btnCancel_actionPerformed(ActionEvent e) {
      hide();
   }

   void testRequired() {
      if ( nsMap.size() > 0 && tblNS.getSelectedRow() != -1 && tblNS.isFocusOwner() )
         btnNSRemove.setEnabled(true);
      else
         btnNSRemove.setEnabled(false);
   }


   /**
    * NSTableSelectionListener
    */

   private class NSTableSelectionListener implements ListSelectionListener {
      public void valueChanged(ListSelectionEvent e) {
         testRequired();
      }
   }


   /**
    * NSTableModel
    */

   private class NSTableModel extends AbstractTableModel implements TableModelListener {
      public NSTableModel() {
         addTableModelListener(this);
      }

      public int getRowCount() {
         return nsMap.size();
      }

      public int getColumnCount() {
         return NSColumnNames.length;
      }

      public Object getValueAt(int rowIndex, int columnIndex) {
         NameValue nv = (NameValue)nsMap.get(rowIndex);
         if ( columnIndex == 0 )
            return nv.name;
         else
            return nv.value;
      }

      public String getColumnName(int column) {
         return NSColumnNames[column];
      }

      public boolean isCellEditable(int rowIndex, int columnIndex) {
         return true;
      }

      public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
         NameValue nv = (NameValue)nsMap.get(rowIndex);
         if ( columnIndex == 0 )
            nv.name = (String)aValue;
         else
            nv.value = (String)aValue;
         fireTableCellUpdated(rowIndex, columnIndex);
      }

      public Class getColumnClass(int columnIndex) {
         return String.class;
      }

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


   /**
    * NameValue
    */

   private class NameValue {
      public String name;
      public String value;

      public NameValue() {
      }

      public NameValue(String name, String value) {
         this.name = name;
         this.value = value;
      }
   }
}


