/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal :
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/

package org.esupportail.portal.channels.CStockage.channelAction.groupManager;
 

import java.net.MalformedURLException;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;
 

import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.NotAuthorizedException;
import org.esupportail.portal.channels.CStockage.exception.NotExistsResourceException;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.provider.ChannelResource;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.jasig.portal.ChannelRuntimeData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Id: ChannelAction.java,v 1.0 24 sept. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: ChannelAction
 * Original Author: Yohan Colmant
 * Class used to manage the actions when we are in a classic space context
 */
public class GroupManagerAction {
 

	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(GroupManagerAction.class);
	
	
	/**
	 * the space containing this channel action
	 */
	private Space groupSpace;
	
	/**
	 * The group tree
	 */
	private UserGroupTree groupTree;
	
	/**
	 * the selection of groups
	 */
	private TreeSet selection;
	
	
	/**
	 * Default constructor
	 */
	public GroupManagerAction(Space currentSpace) throws PropertiesException, ApplicationException {
		
		try {
			// create a space for the groups
			this.groupSpace = (Space)currentSpace.clone();
			
			String aclGroupPrefix = this.groupSpace.getServer().getAclGroupPrefix();
			String newPath = aclGroupPrefix;
			//System.out.println(newPath);
			
			this.groupSpace.setPath(newPath);
			this.groupSpace.setServerAccessObject();
			
			// init the groupTree
			this.groupTree = new UserGroupTree(currentSpace.getKey(), this.groupSpace.getCurrentPath());
			
			//System.out.println("server="+this.groupSpace.getServer().getId()+", space="+this.groupSpace.getKey());
			
			// if the tree is not initialized
			/*if (!this.groupTree.isRootGroupEntryInitialized()) {
				System.out.println("initialise l'arbre de groupes");
				String path = this.groupSpace.getCurrentPath();
				ChannelResource[] groups = this.groupSpace.getServerAccessObject().ls(path);
				if (groups.length>0) {
					String name = groups[0].getName();
					String displayName = groups[0].getDisplayName();
					this.groupTree.initRootGroupEntry(name, displayName, path);
				}
				
			}*/
			
		}
		/*catch(NotExistsResourceException e) {			
			//this.currentSpace.setWebdavAccessObject(null);		
			ApplicationException ex = new ApplicationException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}
		catch(NotAuthorizedException e) {			
			//this.currentSpace.setWebdavAccessObject(null);		
			ApplicationException ex = new ApplicationException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}*/
		catch(ClassNotFoundException e) {			
			//this.currentSpace.setWebdavAccessObject(null);		
			PropertiesException ex = new PropertiesException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}
		catch(MalformedURLException e) {			
			//this.currentSpace.setWebdavAccessObject(null);	
			PropertiesException ex = new PropertiesException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}
		catch(IllegalAccessException e) {			
			//this.currentSpace.setWebdavAccessObject(null);		
			PropertiesException ex = new PropertiesException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}
		catch(InstantiationException e) {			
			//this.currentSpace.setWebdavAccessObject(null);		
			PropertiesException ex = new PropertiesException();
			if (log.isDebugEnabled()){
				log.debug("GroupManagerAction"+" :: "+e);
			}
			throw ex;
		}
		
		
	}
	
	
	
	
	/**
	 * Call the group manager
	 * @return the XML
	 */
	public StringBuffer renderXmlGroupManager(ChannelRuntimeData runtimeData, StringBuffer stylesheet, boolean firstCall, Vector hiddenGroups) throws ApplicationException, NotExistsResourceException, NotAuthorizedException {
		
		// if firstCall
		if (firstCall) {
			this.selection = new TreeSet();
		}
		
		// if we close an entry
		String closeId = runtimeData.getParameter("close");
		if (closeId!=null) {
			groupManagerCloseEntry(closeId);
		}

		// if we open an entry
		String openId = runtimeData.getParameter("open");
		if (openId!=null) {
			groupManagerOpenEntry(openId, hiddenGroups);
		}
		
		// if we add an entry
		String addId = runtimeData.getParameter("add");
		if (addId!=null) {
			groupManagerAddEntry(addId);
		}

		// if we delete an entry
		String deleteId = runtimeData.getParameter("delete");
		if (deleteId!=null) {
			groupManagerDeleteEntry(deleteId);
		}
		
		stylesheet.delete(0, stylesheet.length());
		stylesheet.append("groupManager");
		return renderXmlListGroups();
	}
	
	
	
	
	/**
	 * If finished
	 * @return true if finished
	 */
	public boolean isFinished(ChannelRuntimeData runtimeData) {
		return runtimeData.getParameter("exit_type")!=null;
	}
	
	

	/**
	 * @return the resuts
	 */
	public TreeSet getResults(ChannelRuntimeData runtimeData) {

		// if we exit
		String exitType = runtimeData.getParameter("exit_type");
		if (exitType!=null) {

			// we valid
			if (exitType.equals("ok")) {
				groupManagerValid();
			}
			
			// we cancel
			else if (exitType.equals("cancel")) {
				groupManagerCancel();
			}
		}
		
		return this.selection;
	}
	
	
	
	/**
	 * We valid and exit
	 */
	private void groupManagerValid() {
	}
	
	

	/**
	 * We valid and exit
	 */
	private void groupManagerCancel() {
		this.selection = null;
	}
	
	
	/**
	 * Close an entry
	 * @param id
	 */
	private void groupManagerCloseEntry(String id) {
		
		if (this.groupTree.existGroupEntryId(id)) {
			this.groupTree.setOpen(id, false);
		}
	}
		
	
	/**
	 * Open an entry
	 * @param id
	 */
	private void groupManagerOpenEntry(String id, Vector hiddenGroups) throws ApplicationException, NotExistsResourceException, NotAuthorizedException {
		
		// set open at true
		GroupTreeEntry entry = this.groupTree.getGroupEntry(id);
		if (entry!=null) {
			
			// are children set ?
			boolean childrenSet = entry.isChildrenInitialized();
			
			// if not set, set the children
			if (!childrenSet) {
				//System.out.println("deploie "+entry.getDisplayName());
				
				entry.initChildren();
				
				ChannelResource[] groups = this.groupSpace.getServerAccessObject().ls(entry.getPath(), true);
				
				if (log.isDebugEnabled()) {
					log.debug("groupManagerOpenEntry :: hiddenGroups are "+hiddenGroups);
				}
				
				// for each group in children
				for (int i=0; i<groups.length; i++) {
					
					String name = groups[i].getName();
					String entryPath = entry.getPath();
					if (!entryPath.startsWith("/")) {
						entryPath = "/"+entryPath;
					}
					if (!entryPath.endsWith("/")) {
						entryPath = entryPath+"/";
					}
					String resourcePath = entryPath+name+"/";
					
					// if we can show it
					if (!hiddenGroups.contains(resourcePath)) {
						if (log.isDebugEnabled()) {
							log.debug("groupManagerOpenEntry :: hiddenGroups doesn't contain "+resourcePath+" --> we can show it");
						}
						
						String displayName = groups[i].getDisplayName();
						String uportalRealUri = groups[i].getUportalRealUri();
						GroupTree.addChild(entry, name, displayName, uportalRealUri);
					}
					
					// we can not show it
					else {
						if (log.isDebugEnabled()) {
							log.debug("groupManagerOpenEntry :: hiddenGroups contains "+resourcePath+" --> we can NOT show it");
						}
					}
				}
				
			}
			
			this.groupTree.setOpen(id, true);
		}
		
	}
	
	
	
	/**
	 * Add an entry
	 * @param id
	 */
	private void groupManagerAddEntry(String id) {
		GroupTreeEntry g = this.groupTree.getGroupEntry(id);
		
		if (g!=null && !this.selection.contains(g)) {
			this.selection.add(g);
		}
	}
	

	
	/**
	 * Delete an entry
	 * @param id
	 */
	private void groupManagerDeleteEntry(String id) {
		
		GroupTreeEntry g = this.groupTree.getGroupEntry(id);
		
		if (g!=null) {
			this.selection.remove(g);
		}
	}
	
	
	
	public StringBuffer renderXmlListGroups() {
		StringBuffer xml = new StringBuffer();
		
		// available group
		GroupTreeEntry root = this.groupTree.getRootGroupEntry();
		xml.append(renderXmlAvailableGroup(root));
		
		
		// selection
		xml.append("<selection>\n");
		
		Iterator iter = this.selection.iterator();
		while (iter.hasNext()) {
			GroupTreeEntry group = (GroupTreeEntry)iter.next();
			xml.append("\t"+renderXmlSelectedGroup(group)+"\n");
		}
		xml.append("</selection>\n");
		//System.out.println(xml);
		
		return xml;
	}
	
	
	
	
	public StringBuffer renderXmlAvailableGroup(GroupTreeEntry group) {
		StringBuffer xml = new StringBuffer();
		
		String id = group.getId();
		String displayName = group.getDisplayName();
		displayName = displayName.replace("&","&amp;");
        displayName = displayName.replace("\"","&quot;");
        displayName = displayName.replace(">","&gt;");
        displayName = displayName.replace("<","&lt;");
        
		boolean open = this.groupTree.isOpen(id);
		
		xml.append("<group id=\""+id+"\" displayName=\""+displayName+"\" open=\""+open+"\" hasChild=\""+(open && group.getChildren().size()>0)+"\" selected=\""+(this.selection.contains(group))+"\">\n");
		
		if (open) {
			Iterator iter = group.getChildren().iterator();
			while (iter.hasNext()) {
				GroupTreeEntry gte = (GroupTreeEntry)iter.next();
				xml.append(renderXmlAvailableGroup(gte));
			}
		}
		
		xml.append("</group>\n");
		
		return xml;
	}
	
	
	public StringBuffer renderXmlSelectedGroup(GroupTreeEntry group) {
		StringBuffer xml = new StringBuffer();
		
		String id = group.getId();
		String displayName = group.getDisplayName();
		displayName = displayName.replace("&","&amp;");
        displayName = displayName.replace("\"","&quot;");
        displayName = displayName.replace(">","&gt;");
        displayName = displayName.replace("<","&lt;");
		
		xml.append("<selected_group id=\""+id+"\" displayName=\""+displayName+"\" />");
		
		return xml;
	}
	
	
	
	
	public ServerAccess getServerAccess() {
		return this.groupSpace.getServerAccessObject();
	}
		
}
