/*
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;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portal.channels.CStockage.CStockage;
import org.esupportail.portal.channels.CStockage.channelAction.classic.sharing.SharingTool;
import org.esupportail.portal.channels.CStockage.channelAction.groupManager.GroupManagerAction;
import org.esupportail.portal.channels.CStockage.config.ChannelConfiguration;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.esupportail.portal.channels.CStockage.exception.ApplicationException;
import org.esupportail.portal.channels.CStockage.exception.BadConnexionParameters;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.exception.ConnexionParametersRequired;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.ChannelStaticData;
import org.jasig.portal.IServant;
import org.jasig.portal.PortalException;
import org.jasig.portal.security.IPerson;
import org.jasig.portal.utils.XSLT;
import org.xml.sax.ContentHandler;

/**
 * Id: AbstractChannelAction.java,v 1.0 24 sept. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: AbstractChannelAction
 * Original Author: Yohan Colmant
 * 
 */
public abstract class AbstractChannelAction {
	
	

	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(AbstractChannelAction.class);
	
	
	
	
	/**
	 * the space containing this channel action
	 */
	protected Space currentSpace;
	
  	/**
	 * The default spaces
	 */
	protected ArrayList spaces;
	
	
	
	/**
	 * Object used to keep the objects used between 2 actions, for example, the clipboard
	 */
	protected BufferAction buffer;
	
	/**
	 * The user login in the portal
	 */
	protected String userPortalLogin;
	
	/**
	 * The groups of the user in the portal
	 */
	protected Vector userGroups;
	
	

	/**
	 * The servant channel used for groups and users selection
	 */
	protected IServant slave;
	

	/**
	 * The object used to manage the sharing of folder
	 */
	protected SharingTool sharingTool;
	
	

	/**
	 * The current user IPerson object
	 */
	private IPerson person;
	

	/**
	 * The manager of the groups
	 */
	protected GroupManagerAction groupManager;
	
	
	

	/**
	 * The stylesheet used
	 */
	protected StringBuffer stylesheet;
	
	
	
	/**
	 * Init the object used to manage the actions of the channel
	 * @param person the uportal person object
	 * @param currentSpace the current space used
	 * @param spaces all the spaces used
	 * @param buffer the buffer used to get for example the clipboard
	 * @param userPortalLogin The user login in the portal
	 * @param userGroups The groups of the user in the portal
	 * @throws ChannelException
	 */
	public void init(IPerson person, Space currentSpace, ArrayList spaces, BufferAction buffer, String userPortalLogin, Vector userGroups) throws PropertiesException, ApplicationException {
		this.person = person;
		this.currentSpace = currentSpace;		
		this.spaces = spaces;
		this.buffer = buffer;
		this.userPortalLogin = userPortalLogin;
		this.userGroups = userGroups;
		
		if (log.isDebugEnabled()) {
			log.debug("init"+" :: person="+person);
			log.debug("init"+" :: userPortalLogin="+userPortalLogin);
			log.debug("init"+" :: userGroups="+userGroups);
		}
		
		// init the group manager
		if ((currentSpace.getSharing().equals(Space.SHARING_COMPLEX) || currentSpace.getSharing().equals(Space.SHARING_SIMPLE)) && currentSpace.getServer().allowsPersonalization())
			this.groupManager = new GroupManagerAction(currentSpace);
	}
	
	
	
	/**
	 * Init the current viewer of the space
	 * @throws ChannelException
	 */
	//protected abstract void initPrivilegesOfTheCurrentViewer() throws ChannelException;
	
	
	
	
	/**
	 * Manage the actions when refreshing the channel
	 * @param staticData the static data channel object
	 * @param runtimeData the runtime data channel object
	 * @param out the contentHandler used in the renderXml
	 * @param xslt the xslt motor object
	 * @param setStaticDataException the excpetion throwed in the setStaticData method
	 * @throws PortalException
	 */
	public void checkCalledAction(String currentMode, ChannelStaticData staticData, ChannelRuntimeData runtimeData, ContentHandler out, XSLT xslt, ChannelException setStaticDataException) throws PortalException, BadConnexionParameters, ConnexionParametersRequired {

		// log
		if (log.isDebugEnabled()){
			log.debug("checkCalledAction"+" :: currentMode = "+currentMode);
		}	
		
		// check if servant is active or not
		if (slave!=null) {
			slave.setRuntimeData(runtimeData);
			if (!slave.isFinished()) {								
				slave.renderXML(out);
				return;
			}
			else {								
				currentMode = Constants.VALID_CHANNEL_SERVANT_RESULTS;
			}
		}
		
		// if we support the spaces personalization
		boolean isSpacesPersonalization = false;
		
		// the stylesheet we are going to use
		stylesheet = new StringBuffer();

		// Xml string generated by the diferents methods
		StringBuffer xmlTemp = new StringBuffer();		
		
		try {

			// if we support the spaces personalization
			isSpacesPersonalization = ChannelConfiguration.getInstance().isSpacesPersonalization();
			
			// if password set
			try {				
				if (currentMode!=null && currentMode.equals(Constants.PASSWORD_MODE)) {
					String login = runtimeData.getParameter("loginOfUser");
					String password = runtimeData.getParameter("password");
					this.currentSpace.getServer().setLogin(login);
					this.currentSpace.getServer().setPassword(password);
					
					//System.out.println("je recupere "+login+" "+password);
					//System.out.println("je recupere "+login+" "+password);
					// if the login is different, we check the path if there is {storageFormLogin}, and init the server access object
					this.currentSpace.checkPath(person);
					//System.out.println("1");
					this.currentSpace.initServerAccessObject(person);
					//System.out.println("2");
					// init the channel action object
					//initPrivilegesOfTheCurrentViewer();
					//System.out.println("3");
					currentMode = Constants.SHOW_CURRENT_DIR_MODE;
				}
			}
			catch(MalformedURLException e) {							
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: "+e);
				}
				throw new PropertiesException();
			}
			catch(IllegalAccessException e) {							
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: "+e);
				}
				throw new PropertiesException();
			}	
			catch(InstantiationException e) {							
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: "+e);
				}
				throw new PropertiesException();
			}	
			catch(ClassNotFoundException e) {							
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: "+e);
				}
				throw new PropertiesException();
			}	
			
			
			// if none staticdata exception
			if (setStaticDataException==null) {
				
				// if it the asked authentication, and none password still set
				if (this.currentSpace.getServer().isAskedAuthentication() && this.currentSpace.getServer().getPassword()==null) {
					throw new ConnexionParametersRequired();
				}
				
				// else, connect to the server
				else {
					try {
						this.currentSpace.getServerAccessObject().connect();
						//checkCurrentDirectoryProperties();TODO		
						
						// if connection is ok and if we are in the "asked" mode, we delete regexp
						if (this.currentSpace.getServer().isAskedAuthentication()) {
							this.currentSpace.clearRegexp();
						}
					}
					catch(BadConnexionParameters e) {
						//e.printStackTrace();
						// log
						if (log.isDebugEnabled()){
							log.debug("checkCalledAction"+" :: "+e);
						}
						throw e;
					}
					catch(Exception e) {
						//e.printStackTrace();
						// log
						if (log.isDebugEnabled()){
							log.debug("checkCalledAction"+" :: "+e);
						}
						setStaticDataException= new ServerException();
					}
				}
			}			
			
			// check the setStaticDataException
			if (setStaticDataException!=null) {

				// log
				if (log.isDebugEnabled()){
					log.debug("checkCalledAction"+" :: setStaticDataException = "+setStaticDataException);
				}
				
				throw setStaticDataException;
			}
			
			
			// set the default mod
			if (currentMode == null) {			
				currentMode = Constants.SHOW_CURRENT_DIR_MODE;
			}

			//////////////////////////////////////////////////////
			// N A V I G A T I O N
			// Display the current directory
			if (currentMode.equals(Constants.SHOW_CURRENT_DIR_MODE)) {
				
				// if we change the sort type
				String sort = runtimeData.getParameter("sort");
				if (sort!=null) {
					buffer.setCurrentSortType(sort);
				}
				
				stylesheet = new StringBuffer("CStockage");
				xmlTemp = renderXmlShowCurrentDir(runtimeData);	
			}
			// Go to the parent directory
			else if (currentMode.equals(Constants.DIRECTORY_BACK)) {	
				directoryBack();
				stylesheet = new StringBuffer("CStockage");
				xmlTemp = renderXmlShowCurrentDir(runtimeData);
			}
			
			
			

			//////////////////////////////////////////////////////
			// G R O U P   M A N A G E R
			// Display the current directory
			else if (currentMode.equals(Constants.GROUP_MANAGER)) {
				
				// connect the server
				this.groupManager.getServerAccess().connect();
				
				StringBuffer x = this.groupManager.renderXmlGroupManager(runtimeData, stylesheet, false, this.currentSpace.getServer().getAclHiddenGroupsInTree());
				
				// if finished
				if (this.groupManager.isFinished(runtimeData)) {
					xmlTemp = specificCheckCalledAction(Constants.VALID_GROUPS_RESULTS, staticData, runtimeData, out, xslt, setStaticDataException);
					if (xmlTemp == null)
						return;
				}
				else {
					xmlTemp = x;
				}
				
				// disconnect the server
				this.groupManager.getServerAccess().disconnect();
			}
			

			
			//////////////////////////////////////////////////////
			// S P E C I F I C    A C T I O N
			else  {	
				xmlTemp = specificCheckCalledAction(currentMode, staticData, runtimeData, out, xslt, setStaticDataException);
				if (xmlTemp == null)
					return;
			}

			 
		}
		catch(ServerException e) {
			//e.printStackTrace();
			stylesheet = new StringBuffer("CStockage");			
			
			try {
				if (currentSpace.getServer().isAskedAuthentication()) {
					
					// log
					if (log.isDebugEnabled()){
						log.debug("checkCalledAction"+" :: "+e);
					}
					
					throw new BadConnexionParameters();
				}
				else {
					xmlTemp = renderXmlChannelException(e);
					// log
					if (log.isDebugEnabled()){
						log.debug("checkCalledAction"+" :: "+e);
					}
				}
			}
			catch(PropertiesException ex) {
				xmlTemp = renderXmlChannelException(ex);
			}
		}
		catch(ChannelException e) {
			//e.printStackTrace();
			stylesheet = new StringBuffer("CStockage");
			
			if (e instanceof ConnexionParametersRequired) {
				throw (ConnexionParametersRequired)e;
			}
			if (e instanceof BadConnexionParameters) {
				throw (BadConnexionParameters)e;
			}
			
			xmlTemp = renderXmlChannelException(e);
			// log
			if (log.isDebugEnabled()){
				log.debug("checkCalledAction"+" :: "+e);
			}
		}
		
		
		// disconnect form the server
		try {
			// discconnect from the dav
			this.currentSpace.getServerAccessObject().disconnect();
		}
		catch (Exception e) {
			// log
			if (log.isDebugEnabled()){
				log.debug("checkCalledAction"+" :: "+e);
			}
		}
		// System.out.println(xml+"\n\n\n");
		

		// the xslt transformation
		CStockage.xsltTransformation(xslt, xmlTemp, out, runtimeData, stylesheet, buffer, isSpacesPersonalization);
	
	}
	
	
	
	
	/**
	 * For the selected mode, we check the properties of the current directory
	 * @throws Exception
	 */
	//protected abstract void checkCurrentDirectoryProperties() throws Exception;
	
	
	
	
	
	/**
	 * Return the xml when we have to show a information message
	 * @return the xml when we have to show a information message
	 */
	public abstract StringBuffer renderXmlWithInformation(String informationCode) throws ChannelException ;
	
	
	/**
	 * Return the xml when we have a BadConnexionParameters exception
	 * @param e the throwed exception
	 * @return the xml when we have a BadConnexionParameters exception
	 */
	public abstract StringBuffer renderXmlBadConnexionParametersException(ChannelException e) throws PropertiesException;
	
	
	/**
	 * Return the xml when we have a ChannelException exception
	 * @param e the throwed exception
	 * @return the xml when we have a ChannelException exception
	 */
	public abstract StringBuffer renderXmlChannelException(ChannelException e);
	
	

	
	
	
	
	
	/**
	 * Manage the specific actions when refreshing the channel for the specific channel mode
	 * @param currentMode the current channel mode
	 * @param staticData the static data channel object
	 * @param runtimeData the runtime data channel object
	 * @param out the contentHandler used in the renderXml
	 * @param xslt the xslt motor object
	 * @param setStaticDataException the excpetion throwed in the setStaticData method
	 * @throws PortalException
	 */
	public abstract StringBuffer specificCheckCalledAction(String currentMode, ChannelStaticData staticData, ChannelRuntimeData runtimeData, ContentHandler out, XSLT xslt, ChannelException setStaticDataException) throws ChannelException, PortalException ;
	
	
	
	
	
	
	

	/**
	 * Generate the XML String for this mod
	 * @param runtimeData the runtime data channel object
	 * @return le XML pour ce mode
	 * @throws ChannelException
	 */
	protected abstract StringBuffer renderXmlShowCurrentDir(ChannelRuntimeData runtimeData) throws ChannelException;
	
	
	/**
	 * Go to the parent directory
	 * @throws ChannelException
	 */
	protected abstract void directoryBack() throws ChannelException;
	
	
}
