/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.usermanagement.gui.userlist;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Vector;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.utils.GECAMedTitledBorder;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedUser;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.Permission;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.Role;
import lu.tudor.santec.gecamed.usermanagement.gui.AdminModule;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 * JPanel to edit the roles of the users, and show the rights of the different roles.
 *
 * @version
 * <br>$Log: RolePanel.java,v $
 * <br>Revision 1.19  2013-12-27 18:09:26  donak
 * <br>Cleanup of imports
 * <br>
 * <br>Revision 1.18  2013-07-15 06:18:37  ferring
 * <br>logging changed
 * <br>
 * <br>Revision 1.17  2013-03-01 16:01:06  ferring
 * <br>tidied up this class
 * <br>
 * <br>Revision 1.16  2011-11-29 09:38:23  ferring
 * <br>imports removed
 * <br>
 * <br>Revision 1.15  2008-10-07 09:34:37  heinemann
 * <br>translations of roles and rights;
 * <br>show only  roles and rights of the activated modules in the usermanagement section
 * <br>
 * <br>Revision 1.14  2008-10-03 15:08:32  heinemann
 * <br>Role translations
 * <br>
 * <br>Revision 1.13  2008-09-25 09:43:10  heinemann
 * <br>fixed copyrights
 * <br>
 * <br>Revision 1.12  2008-01-15 10:18:39  hermen
 * <br>updated Javadoc and refactured code
 * <br>
 *
 */
public class RolePanel extends JPanel {

	private static final long serialVersionUID = 1L;
	
	/**
	 * static logger for this class
	 */
	private static Logger logger = Logger.getLogger(RolePanel.class.getName());
	
	private JTable rolesTable;
	private JTable permissionsTable;
	private GecamedUser currentUser;
//	private UserAdminInterface manager;
	private RoleTableModel roleTableModel;
	private PermissionTableModel permissionTableModel;
	private UserManagementPanel userManagementPanel;

	public RolePanel(UserManagementPanel userManagementPanel) {
		this.setOpaque(false);
		this.userManagementPanel = userManagementPanel;
		this.setLayout(new GridLayout(1, 0));

		// Get the type manager
//		this.manager = (UserAdminInterface) ManagerFactory.getRemote(UserAdminBean.class);
		
		this.permissionTableModel = new PermissionTableModel();

		this.roleTableModel = new RoleTableModel(permissionTableModel);
		this.rolesTable = new JTable(this.roleTableModel);
		this.rolesTable.getColumnModel().getColumn(0).setMaxWidth(30);
		this.rolesTable.getColumnModel().getColumn(2).setMaxWidth(50);
		JScrollPane jspRoles = new JScrollPane(rolesTable);
		jspRoles.setOpaque(false);
		jspRoles.getViewport().setOpaque(false);
		jspRoles.setPreferredSize(new Dimension(100, 400));
		jspRoles.setBorder(new GECAMedTitledBorder(Translatrix
				.getTranslationString("um.roles")));
		this.add(jspRoles);

		this.permissionsTable = new JTable(this.permissionTableModel);
		this.permissionsTable.setEnabled(false);
		JScrollPane jspPermissions = new JScrollPane(permissionsTable);
		this.permissionsTable.getColumnModel().getColumn(0).setMaxWidth(30);
		this.permissionsTable.getColumnModel().getColumn(2).setMaxWidth(50);
		/* ------------------------------------------------------ */
		// set renderer
		this.permissionsTable.getColumnModel().getColumn(0).setCellRenderer(
				new PermissionCellRenderer());
		this.permissionsTable.getColumnModel().getColumn(1).setCellRenderer(
				new PermissionCellRenderer());
		
		this.permissionsTable.getColumnModel().getColumn(2).setCellRenderer(
				new ImagePermissionCellRenderer());
		/* ------------------------------------------------------ */

		jspPermissions.setOpaque(false);
		jspPermissions.getViewport().setOpaque(false);
		jspPermissions.setPreferredSize(new Dimension(100, 150));
		jspPermissions.setBorder(new GECAMedTitledBorder(Translatrix
				.getTranslationString("um.permissions")));
		this.add(jspPermissions);

		this.rolesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener()
		{
			public void valueChanged(ListSelectionEvent e)
			{
				Role r = roleTableModel.getRole(rolesTable.getSelectedRow());
				if (r != null)
				{
					// TODO here we must change something!
					permissionTableModel.setRolePermissions(r.getPermissions());
				}
				else
				{
					permissionTableModel.setRolePermissions(null);
				}
			}
		});

	}

	/**
	 * @param User The User to set.
	 */
	public void setUser(GecamedUser currentUser) {
		this.currentUser = currentUser;
		this.roleTableModel.setUser(this.currentUser);
		try {
			this.rolesTable.setRowSelectionInterval(0, 0);
		} catch (Exception e) {
		}
		/* ------------------------------------------------------ */
		// push the user permissions, gained from the roles
		// to the permission table
		try {
			this.permissionTableModel.setUserPermissions(
					currentUser.getGrantedPermissions());
		} catch (Exception e) {
		}
		/* ------------------------------------------------------ */
	}

	// ###############################################
	class RoleTableModel extends AbstractTableModel {
		/* ******************************************************** */
		// Class Members
		
		private static final long serialVersionUID = 1L;
		/* ------------------------------------------------------ */
		private String[] columnNames = {
				Translatrix.getTranslationString("um.id"),
				Translatrix.getTranslationString("um.name"),
				Translatrix.getTranslationString("um.set")};
		/* ------------------------------------------------------ */
		private Class<?>[] columnsClasses = {Integer.class, String.class,
				Boolean.class};
		/* ------------------------------------------------------ */
		private Vector<Role> allRoles;
		private GecamedUser user = null;
		private PermissionTableModel permissionTableModel;
		private boolean editable;

		// End of Class Members
		/* ******************************************************** */
		/**
		 * 
		 */
		public RoleTableModel(PermissionTableModel permissionTableModel) {
			/* ================================================== */

//			this.allRoles = new ArrayList(manager.getRoles());
			
			this.allRoles = new Vector<Role>(GECAMedModule.getAllRoles());
			
			this.permissionTableModel = permissionTableModel;
			/* ================================================== */
		}

		/**
		 * @param user
		 */
		public void setUser(GecamedUser user) {
			this.user = user;
			fireTableDataChanged();
		}

		/**
		 * @param row
		 * @return
		 */
		public Role getRole(int row) {
			try {
				return allRoles.get(row);
			} catch (Exception e) {
				return null;
			}
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#isCellEditable(int, int)
		 */
		public boolean isCellEditable(int row, int col) {
			// only status-checkbox is editable.
			if (editable && col == 2) {
				return true;
			}
			return false;
		}

		/*
		 * JTable uses this method to determine the default renderer/ editor for
		 * each cell. If we didn't implement this method, then the last column
		 * would contain text ("true"/"false"), rather than a check box.
		 */
		public Class<?> getColumnClass(int c) {
			return columnsClasses[c];
		}

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

		public String getColumnName(int col) {
			return columnNames[col];
		}

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

		/*
		 * sets the data on Table and DB
		 */
		public void setValueAt(Object value, int row, int col) {
			switch (col) {
				case 0 :
					break;
				case 1 :
					break;
				case 2 :
					try {
						if ((Boolean) value) {
							if (user.getRoles() == null) {
								user.setRoles(new HashSet<Role>());
							}
							user.getRoles().add(allRoles.get(row));
							/* ------------------------------------------------------ */
						} else {
							user.getRoles().remove(allRoles.get(row));
							if (user.getRoles().size() == 0) {
								user.setRoles(null);
							}
							/* ------------------------------------------------------ */
						} 
					}catch (Exception e) {
						logger.log(Level.WARN, "setting roles failed", e);
					}
					break;
			}
			fireTableCellUpdated(row, col);
			user.setHasChanges(true);
			userManagementPanel.updateTable();
			// update the permissions
			// remove or add the permissions of the role
			permissionTableModel.setUserPermissions(user.getGrantedPermissions());
			permissionTableModel.fireTableDataChanged();
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int row, int col) {
			try {
				Role role = allRoles.get(row);
				switch (col) {
					case 0 :
						return role.getId();
					case 1 : {
						/* ------------------------------------------------------- */
						String s = Translatrix.getTranslationString("role."+role.getName());
//						return role.getName();
						return s;
						/* ------------------------------------------------------- */
					}
					case 2 :
						try {
							return new ArrayList<Role>(user.getRoles()).contains(role);
						} catch (Exception e) {
						}
						return false;
				}
			} catch (Exception e) {
				logger.log(Level.WARN, "reading roles failed", e);
			}
			return null;
		}

		public void setEditable(boolean enable) {
			this.editable = enable;
		}
	}

	//  ###############################################
	class PermissionTableModel extends AbstractTableModel {

		private static final long serialVersionUID = 1L;

		private String[] columnNames = {
				Translatrix.getTranslationString("um.id"),
				Translatrix.getTranslationString("um.name"),
				Translatrix.getTranslationString("um.set")};

		private Class<?>[] columnsClasses = {Integer.class, String.class,
				Boolean.class};

		private Vector<Permission> allPermissions;
		private Collection<Permission> userPermissions;

		private Collection<Permission> rolePermissions;
		
		/**
		 * 
		 */
		public PermissionTableModel() {
//			this.allPermissions = new ArrayList(manager.getPermissions());
			
			this.allPermissions = new Vector<Permission>();
			this.allPermissions.addAll(GECAMedModule.getAllPermissions());
		}

		/**
		 * Set the permissions of a user
		 * 
		 * @param userPermissions
		 */
		public void setUserPermissions(Collection<Permission> userPermissions) {
			this.userPermissions = userPermissions;
			fireTableDataChanged();
		}

		/**
		 * 
		 * Returns all permissions for the user
		 * @return
		 */
		public Collection<Permission> getUserPermissions() {
			/* ====================================================== */
			return this.userPermissions;
			/* ====================================================== */
		}
		
		
		/**
		 * Sets the permissions of a role
		 * 
		 * @param rolePermissions
		 */
		public void setRolePermissions(Collection<Permission> rolePermissions) {
			/* ====================================================== */
			this.rolePermissions = rolePermissions;
			fireTableDataChanged();
			/* ====================================================== */
		}
		
		/**
		 * returns if the given permission is member of 
		 * a role that was given by the method setRolePermissions
		 * 
		 * @param permissionId
		 * @return
		 */
		public boolean isPermissionOfRole(Integer permissionId) {
			/* ====================================================== */
			if (rolePermissions == null) {
				return false;
			}
			for (Permission p : rolePermissions) {
				/* ------------------------------------------------------ */
				if (p.getId().equals(permissionId))
					return true;
				/* ------------------------------------------------------ */
			}
			return false;
			/* ====================================================== */
		}
		
		
		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#isCellEditable(int, int)
		 */
		public boolean isCellEditable(int row, int col) {
			return false;
		}

		/*
		 * JTable uses this method to determine the default renderer/ editor for
		 * each cell. If we didn't implement this method, then the last column
		 * would contain text ("true"/"false"), rather than a check box.
		 */
		public Class<?> getColumnClass(int c) {
			return columnsClasses[c];
		}

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

		public String getColumnName(int col) {
			return columnNames[col];
		}

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

		/* (non-Javadoc)
		 * @see javax.swing.table.TableModel#getValueAt(int, int)
		 */
		public Object getValueAt(int row, int col) {
			try {
				Permission permission = allPermissions.get(row);
				switch (col) {
					case 0 :
						return permission.getId();
					case 1 :
						return Translatrix.getTranslationString("permission."+permission.getName());
					case 2 :
						try {
							return userPermissions.contains(permission);
						} catch (Exception e) {
						}
						return false;
				}
			} catch (Exception e) {
				logger.log(Level.WARN, "reading permissions failed", e);
			}
			return null;
		}
	}


	/**
	 * CellRenderer to render the permissions 
	 *
	 * @version
	 * <br>$Log: RolePanel.java,v $
	 * <br>Revision 1.19  2013-12-27 18:09:26  donak
	 * <br>Cleanup of imports
	 * <br>
	 * <br>Revision 1.18  2013-07-15 06:18:37  ferring
	 * <br>logging changed
	 * <br>
	 * <br>Revision 1.17  2013-03-01 16:01:06  ferring
	 * <br>tidied up this class
	 * <br>
	 * <br>Revision 1.16  2011-11-29 09:38:23  ferring
	 * <br>imports removed
	 * <br>
	 * <br>Revision 1.15  2008-10-07 09:34:37  heinemann
	 * <br>translations of roles and rights;
	 * <br>show only  roles and rights of the activated modules in the usermanagement section
	 * <br>
	 * <br>Revision 1.14  2008-10-03 15:08:32  heinemann
	 * <br>Role translations
	 * <br>
	 * <br>Revision 1.13  2008-09-25 09:43:10  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.12  2008-01-15 10:18:39  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 *
	 */
	class PermissionCellRenderer extends DefaultTableCellRenderer {

		private static final long serialVersionUID = 1L;
		
		private Color green = new Color(174, 232, 127, 85);
		private Color blue = new Color(220, 226, 251, 45);
		
		public PermissionCellRenderer() {
			/* ====================================================== */
//			this.setHorizontalAlignment(JLabel.CENTER);
			/* ====================================================== */
		}


		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) 
		{
			/* ====================================================== */
			super.getTableCellRendererComponent(table, value, isSelected,
						hasFocus, row, column);
			/* ------------------------------------------------------ */
			// table model
			PermissionTableModel tm = (PermissionTableModel) table.getModel();
			
			// the background
//			if ((Boolean) table.getModel().getValueAt(row, 2)) {
			if (tm.isPermissionOfRole((Integer) tm.getValueAt(row, 0))) {
				
				/* ------------------------------------------------------ */
				// if this permission is granted, we want to have a nice
				// and fancy green background
				this.setBackground(green);
				/* ------------------------------------------------------ */
			} else {
				/* ------------------------------------------------------ */
				this.setBackground(blue);
				/* ------------------------------------------------------ */
			}
			/* ------------------------------------------------------ */
			return this;
			/* ====================================================== */
		}

	}
	
	/* ************************************************************ */
	
	
	/**
	 * Cellrenderer to replace the checkbox by nice images
	 * 
	 * @author martin.heinemann@tudor.lu
	 *
	 *
	 * @version
	 * <br>$Log: RolePanel.java,v $
	 * <br>Revision 1.19  2013-12-27 18:09:26  donak
	 * <br>Cleanup of imports
	 * <br>
	 * <br>Revision 1.18  2013-07-15 06:18:37  ferring
	 * <br>logging changed
	 * <br>
	 * <br>Revision 1.17  2013-03-01 16:01:06  ferring
	 * <br>tidied up this class
	 * <br>
	 * <br>Revision 1.16  2011-11-29 09:38:23  ferring
	 * <br>imports removed
	 * <br>
	 * <br>Revision 1.15  2008-10-07 09:34:37  heinemann
	 * <br>translations of roles and rights;
	 * <br>show only  roles and rights of the activated modules in the usermanagement section
	 * <br>
	 * <br>Revision 1.14  2008-10-03 15:08:32  heinemann
	 * <br>Role translations
	 * <br>
	 * <br>Revision 1.13  2008-09-25 09:43:10  heinemann
	 * <br>fixed copyrights
	 * <br>
	 * <br>Revision 1.12  2008-01-15 10:18:39  hermen
	 * <br>updated Javadoc and refactured code
	 * <br>
	 * <br>Revision 1.11  2007-11-20 08:58:54  hermen
	 * <br>moved Managerfactory to core.utils and refactured code to use ManagerFactory instead of context.lookup
	 * <br>
	 * <br>Revision 1.10  2007-09-21 12:58:32  hermen
	 * <br>make Amin Module uneditable in Demo mode
	 * <br>
	 * <br>Revision 1.9  2007/06/19 11:28:04  hermen
	 * <br>added logging
	 * <br>
	 * <br>Revision 1.8  2007/03/02 08:28:44  hermen
	 * <br>initial checkin after the merge of PatientModuleRebuild with the main HEAD
	 * <br>
	 * <br>Revision 1.7.2.1  2006/12/20 08:35:01  hermen
	 * <br>fixed nullpointer
	 * <br>
	 * <br>Revision 1.7  2006/11/20 12:50:18  heinemann
	 * <br>a better guification for editing the user-permissions
	 * <br>
	 * <br>Revision 1.6  2006/11/17 15:14:13  heinemann
	 * <br>icons for permissions
	 * <br>
	 */
	class ImagePermissionCellRenderer extends DefaultTableCellRenderer {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		private Color green = new Color(174, 232, 127, 85);
		private Color red = new Color(255, 213, 213, 45);
		
		private ImageIcon trueIcon;
		private ImageIcon falseIcon;

		public ImagePermissionCellRenderer() {
			/* ====================================================== */
			this.setHorizontalAlignment(JLabel.CENTER);
			// init the icons
			trueIcon = AdminModule.getSmallIcon(AdminModule.ICON_OK);
			falseIcon = AdminModule.getSmallIcon(AdminModule.ICON_ERROR);
			/* ====================================================== */
		}

		/* (non-Javadoc)
		 * @see lu.tudor.santec.gecamed.usermanagement.gui.userlist.RolePanel.PermissionCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
		 */
		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			/* ====================================================== */
			
				/* ------------------------------------------------------ */
				Icon image = null;
				if (value != null) {
					/* ------------------------------------------------------ */
					if (value instanceof Boolean)
						if ((Boolean) value)
							/* ------------------------------------------------------ */
							image = trueIcon;
					/* ------------------------------------------------------ */
						else
							image = falseIcon;
					/* ------------------------------------------------------ */
				} else
					image = falseIcon;
				/* ------------------------------------------------------ */
				//    		return image;
				super.getTableCellRendererComponent(table, image, isSelected,
						hasFocus, row, column);
				/* ------------------------------------------------------ */
				/* ------------------------------------------------------ */
				// the background
				if ((Boolean) table.getModel().getValueAt(row, 2)) {
					/* ------------------------------------------------------ */
					// if this permission is granted, we want to have a nice
					// and fancy green background
					this.setBackground(green);
					/* ------------------------------------------------------ */
				} else {
					/* ------------------------------------------------------ */
					this.setBackground(red);
					/* ------------------------------------------------------ */
				}
				/* ------------------------------------------------------ */
			
			return this;
			/* ====================================================== */
		}

		/* (non-Javadoc)
		 * @see javax.swing.table.DefaultTableCellRenderer#setValue(java.lang.Object)
		 */
		@Override
		protected void setValue(Object value) {
			/* ============================================= */
			super.setIcon((Icon) value);
			/* ============================================= */
		}

	}

	public void setEditable(boolean enable) {
		roleTableModel.setEditable(enable);
	}

}
