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: PermissionsDialog.java,v 1.3 2004/02/12 00:17:54 bradford Exp $
 */

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

import com.dbxml.db.admin.Admin;
import com.dbxml.db.client.CollectionClient;
import com.dbxml.db.common.security.AccessManagerClient;
import com.dbxml.db.core.security.Access;
import com.dbxml.util.dbXMLException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * PermissionsDialog
 */

public final class PermissionsDialog extends JDialog {
   private static final String[] EmptyStrings = new String[0];

   private static final int[] INTS = {Access.READ, Access.WRITE, Access.EXECUTE, Access.CREATE};
   private static final String[] STRS = {
      "Read (Documents & Values)",
      "Write (Documents & Values)",
      "Execute (Extensions)",
      "Create (Collections, Indexes, etc...)"
   };

   private JCheckBox[] chk;
   private CollectionClient col;
   private String roleID;

   ImageIcon imgRole;
   GridBagLayout thisLayout = new GridBagLayout();
   JLabel lblPerms = new JLabel();
   JPanel pnlButtons = new JPanel();
   JButton btnOK = new JButton();
   BorderLayout pnlButtonsLayout = new BorderLayout();
   JButton btnCancel = new JButton();
   JLabel lblRole = new JLabel();
   JLabel lblPermissions = new JLabel();
   JComboBox cmbRole = new JComboBox();
   JPanel pnlPermissions = new JPanel();
   GridLayout layoutPermissions = new GridLayout();
   JPanel pnlRole = new JPanel();
   JLabel lblRoleID = new JLabel();
   CardLayout pnlRoleLayout = new CardLayout();
   JCheckBox chkRecursive = new JCheckBox();
   JLabel lblRecursive = new JLabel();
   JPanel pnlDialog = new JPanel();

   public PermissionsDialog(Frame owner, CollectionClient col, String roleID) {
      super(owner, true);

      this.col = col;
      this.roleID = roleID;

      try {
         jbInit();

         int permissions = 0;

         AccessManagerClient manager = new AccessManagerClient(col.getClient());
         if ( roleID == null ) {
            Set set = new TreeSet();
            String[] roles = manager.listRoles();
            for ( int i = 0; i < roles.length; i++ )
               set.add(roles[i]);

            Map acl = manager.listAccessControl(col.getCanonicalName());
            Iterator iter = acl.keySet().iterator();
            while ( iter.hasNext() )
               set.remove((String)iter.next());

            roles = (String[])set.toArray(EmptyStrings);

            for ( int i = 0; i < roles.length; i++ ) {
               cmbRole.addItem(roles[i]);
               if ( roles[i].equals(roleID) )
                  cmbRole.setSelectedIndex(i);
            }
            pnlRoleLayout.show(pnlRole, "combo");
         }
         else {
            Map permMap = manager.listAccessControl(col.getCanonicalName());
            Integer permInt = (Integer)permMap.get(roleID);
            if ( permInt != null )
               permissions = permInt.intValue();

            lblRoleID.setText(roleID);
            pnlRoleLayout.show(pnlRole, "label");
         }

         chk = new JCheckBox[STRS.length];
         for ( int i = 0; i < STRS.length; i++ ) {
            chk[i] = new JCheckBox(STRS[i]);
            chk[i].setSelected((permissions & INTS[i]) != 0);
            pnlPermissions.add(chk[i]);
         }

         updateButtons();

         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 ) {
         e.printStackTrace();
      }
   }

   public PermissionsDialog(Frame owner, CollectionClient col) {
      this(owner, col, null);
   }

   private void jbInit() throws Exception {
      imgRole = new ImageIcon(PermissionsDialog.class.getResource("role.gif"));

      this.setModal(true);
      this.setTitle("Modify Permissions");
      this.setResizable(false);

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

      lblPerms.setIcon(imgRole);
      pnlButtons.setLayout(pnlButtonsLayout);
      btnOK.setFont(new Font("Dialog", 0, 12));
      btnOK.setActionCommand("ok");
      btnOK.setSelected(true);
      btnOK.setText("ok");
      btnOK.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnOK_actionPerformed(e);
         }
      });
      pnlButtonsLayout.setHgap(5);
      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);
         }
      });
      lblRole.setText("Role");
      lblPermissions.setText("Permissions");
      pnlPermissions.setLayout(layoutPermissions);
      layoutPermissions.setColumns(1);
      layoutPermissions.setRows(0);
      layoutPermissions.setVgap(10);
      pnlRole.setLayout(pnlRoleLayout);
      cmbRole.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(ActionEvent e) {
            cmbRole_actionPerformed(e);
         }
      });
      chkRecursive.setActionCommand("recursive");
      chkRecursive.setText("Apply to all children");
      chkRecursive.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(ActionEvent e) {
            chkRecursive_actionPerformed(e);
         }
      });
      lblRecursive.setText("Recursive");
      pnlDialog.add(lblPerms, new GridBagConstraints(0, 0, 1, 3, 0.0, 0.0
            ,GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(10, 10, 10, 10), 0, 0));
      pnlDialog.add(pnlButtons, new GridBagConstraints(1, 3, 2, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 10, 10), 0, 0));
      pnlButtons.add(btnOK, BorderLayout.CENTER);
      pnlButtons.add(btnCancel, BorderLayout.EAST);
      pnlDialog.add(lblPermissions, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0
            ,GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(0, 10, 10, 0), 0, 0));
      pnlDialog.add(lblRole, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(10, 10, 10, 0), 0, 0));
      pnlDialog.add(pnlPermissions, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 10, 10, 10), 0, 0));
      pnlDialog.add(pnlRole, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10, 10, 10, 10), 0, 0));
      pnlRole.add(cmbRole,   "combo");
      pnlRole.add(lblRoleID,  "label");
      pnlDialog.add(chkRecursive, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 10, 10, 10), 0, 0));
      pnlDialog.add(lblRecursive, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 10, 10, 0), 0, 0));
   }

   void btnOK_actionPerformed(ActionEvent e) {
      boolean recursive = chkRecursive.isSelected();
      if ( recursive ) {
         StringBuffer sb = new StringBuffer();
         sb.append("Applying permissions for this Role recursively will\n");
         sb.append("override the settings in this Collection and all of\n");
         sb.append("its children.  Are you sure you want to do this?");

         String title = "Confirm Recursive";
         String message = sb.toString();

         int res = JOptionPane.showConfirmDialog(this, message, title, JOptionPane.YES_NO_OPTION);
         if ( res == JOptionPane.NO_OPTION )
            return;
      }

      try {
         AccessManagerClient manager = new AccessManagerClient(col.getClient());

         int permissions = 0;
         for ( int i = 0; i < INTS.length; i++ )
            if ( chk[i].isSelected() )
               permissions |= INTS[i];

         process(manager, col, roleID, permissions, recursive);
      }
      catch ( dbXMLException ex ) {
         Admin.getInstance().addMessage(ex.getMessage());
      }
      hide();
   }

   protected void process(AccessManagerClient manager, CollectionClient col, String roleID, int permissions, boolean recursive) throws dbXMLException {
      String colName = col.getCanonicalName();

      int allPerms = 0;
      for ( int i = 0; i < INTS.length; i++ )
         allPerms |= INTS[i];

      manager.revoke(colName, roleID, allPerms);
      manager.grant(colName, roleID, permissions);

      if ( recursive ) {
         String[] children = col.listCollections();
         for ( int i = 0; i < children.length; i++ ) {
            CollectionClient child = col.getCollection(children[i]);
            process(manager, child, roleID, permissions, recursive);
         }
      }
   }

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

   void cmbRole_actionPerformed(ActionEvent e) {
      roleID = (String)cmbRole.getSelectedItem();
      updateButtons();
   }

   private void updateButtons() {
      for ( int i = 0; chk != null && i < chk.length; i++ )
         chk[i].setEnabled(roleID != null);
      btnOK.setEnabled(roleID != null);
   }

   void chkRecursive_actionPerformed(ActionEvent e) {

   }
}
