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

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.TreeSet;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.esupportail.portal.channels.CStockage.channelAction.AbstractDefaultRenderXml;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.MetaDataConstants;
import org.esupportail.portal.channels.CStockage.channelAction.injac.metadata.MetaDataManager;
import org.esupportail.portal.channels.CStockage.config.ChannelConfiguration;
import org.esupportail.portal.channels.CStockage.config.ServerConstants;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.esupportail.portal.channels.CStockage.exception.AnyVisibleSpaceException;
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.exception.ServerException;
import org.esupportail.portal.channels.CStockage.exception.ChannelException;
import org.esupportail.portal.channels.CStockage.provider.ChannelResource;
import org.esupportail.portal.channels.CStockage.provider.SortedChannelResource;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;


/**
 * Id: DefaultRenderXml.java,v 1.0 27 sept. 2004
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)
 * Classes: DefaultRenderXml
 * Original Author: Yohan Colmant
 * Get the XML to show the curent dir<br/>
 */
public class DefaultRenderXml extends AbstractDefaultRenderXml {
	

	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(DefaultRenderXml.class);
	
	

	
	/**
	 * Return the XML representing the curent dir
	 * @param spaces the spaces list
	 * @param currentSpace the current space used
	 * @param error the error exception
	 * @param information this information message
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param directoryProperties 
	 * @param currentSortType The current and default sort type for the resources
	 * @return the xml generated
	 */
	public static StringBuffer getXml(ArrayList spaces, Space currentSpace, ChannelException error, String information, String userPortalLogin, Vector userGroups, DirectoryProperties directoryProperties, String currentSortType) {				
		
		StringBuffer xml = new StringBuffer();
				
		int erreurInterne = -1;
		
		if (currentSpace!=null) {

			ServerAccess access = currentSpace.getServerAccessObject();
			
			// the content of the directory
			String path = currentSpace.getCurrentPath();
		
			try {																
				
				// the action bar
				xml.append(getXmlAction(currentSpace, userPortalLogin, userGroups, directoryProperties));			
				
				// construct the ressources
				ChannelResource[] ressources = new ChannelResource[0];
				
				// we try if we are authorized
				try {
					if (access!=null)
						ressources = access.ls(path, false);				
				}
				catch(NotAuthorizedException e) {
					if (log.isDebugEnabled()){
						log.debug("getXml"+" :: "+e);
					}
					erreurInterne = e.getErrorCode();											
				}			
				catch(NotExistsResourceException e) {
					if (log.isDebugEnabled()){
						log.debug("getXml"+" :: "+e);
					}
					erreurInterne = e.getErrorCode();																			
				}
				
				// the content of the directory	
				xml.append(getXmlContent(currentSpace, ressources, userPortalLogin, userGroups, directoryProperties, currentSortType));			
							
			}
			catch(ChannelException e) {			
				erreurInterne = e.getErrorCode();
				if (log.isDebugEnabled()){
					log.debug("getXml"+" :: "+e);
				}
			}		
			
			// the error bar
			xml.append(getXmlError(error, erreurInterne));
			
			// the information bar
			xml.append(getXmlInformation(information));		
			
			// the navigation bar			
			try {
				xml.append(getXmlNavigation(spaces, currentSpace));										
			}
			catch(PropertiesException ex) {
				return getXmlError(ex, -1);
			}
			
			return xml;
		}
		
		else {
			return getXmlError(new AnyVisibleSpaceException(), -1);
		}
	}
	
	
	
	
	
	/**
	 * Get the XML for the action bar
	 * @param currentSpace the current space used
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param directoryProperties the current directory properties
	 * @return the XML as a StringBuffer
	 * @throws PropertiesException
	 * @throws ServerException
	 */
	private static StringBuffer getXmlAction(Space currentSpace, String userPortalLogin, Vector userGroups, DirectoryProperties directoryProperties) throws PropertiesException, ServerException {
			
		boolean manager = directoryProperties.isUserManager();
		boolean writer = directoryProperties.isUserWriter();
		boolean editor = directoryProperties.isUserEditor();
		
		String directoryType = directoryProperties.getType();
		if (directoryType==null)
			directoryType="";
		
		StringBuffer xmlTemp = new StringBuffer();
		
		xmlTemp.append("<ACTIONS>");
		
		if (currentSpace.getPathSize()>1) {
			xmlTemp.append("<PARENT>"+true+"</PARENT>");
		}
		xmlTemp.append("<REFRESH>"+true+"</REFRESH>");
		
		// if we are not in a space
		if (!directoryType.equals(MetaDataConstants.INJAC_TYPE_SPACE)) {
			xmlTemp.append("<DIRECTORY>"+true+"</DIRECTORY>");
			xmlTemp.append("<UPLOAD>"+true+"</UPLOAD>");	
			
			xmlTemp.append("<COPY>"+true+"</COPY>");
			xmlTemp.append("<MOVE>"+true+"</MOVE>");
			xmlTemp.append("<PASTE>"+true+"</PASTE>");
			
			xmlTemp.append("<RENAME>"+true+"</RENAME>");
			xmlTemp.append("<DELETE>"+true+"</DELETE>");
		}	
		
		else {
			// if not writer, not editor, not manager
			if ( writer || manager || editor ) {				
			
				xmlTemp.append("<COPY>"+true+"</COPY>");
				xmlTemp.append("<MOVE>"+true+"</MOVE>");
				xmlTemp.append("<PASTE>"+true+"</PASTE>");
				
				xmlTemp.append("<RENAME>"+true+"</RENAME>");
				xmlTemp.append("<DELETE>"+true+"</DELETE>");
			
			}
		}
				
		// if we are editor or writer
		if (writer || editor) {
			xmlTemp.append("<UNPUBLISH>"+true+"</UNPUBLISH>");
			xmlTemp.append("<METADATA>"+true+"</METADATA>");
			//xmlTemp.append("<SUBMIT>"+true+"</SUBMIT>");
		}
		
		// if we are writer and not editor
		if (writer) {
			xmlTemp.append("<SUBMIT>"+true+"</SUBMIT>");
		}
		
		// if we are editor
		if (editor) {
			xmlTemp.append("<PUBLISH>"+true+"</PUBLISH>");		
			xmlTemp.append("<REFUSE>"+true+"</REFUSE>");
			xmlTemp.append("<ROOT_DOCUMENT>"+true+"</ROOT_DOCUMENT>");
		}				
		
		// if the current dir is a space				
		if (directoryType.equals(MetaDataConstants.INJAC_TYPE_SPACE)) {
			
			// if the user is manager in this space			
			if (manager) {			
				xmlTemp.append("<ADMIN>"+true+"</ADMIN>");
				xmlTemp.append("<SPACE>"+true+"</SPACE>");
			}
		}
		
		
		xmlTemp.append("</ACTIONS>");
		
		return xmlTemp;		
	}
	
	
	
	/**
	 * Get the XML for the content
	 * @param currentSpace the current space used
	 * @param resources all the ChannelWebdavResource objects
	 * @param userPortalLogin the user portal login
	 * @param userGroups the user portal groups
	 * @param directoryProperties the current directory properties
	 * @param currentSortType The current and default sort type for the resources
	 * @return the XML as a StringBuffer
	 * @throws PropertiesException
	 * @throws ServerException
	 */
	private static StringBuffer getXmlContent(Space currentSpace, ChannelResource[] resources, String userPortalLogin, Vector userGroups, DirectoryProperties directoryProperties, String currentSortType) throws PropertiesException, ServerException {
		
		StringBuffer xmlResources = new StringBuffer();
		
		String path = currentSpace.getCurrentPath();
		
		boolean userIsWriterOnSpace = directoryProperties.isUserWriter();
		boolean userIsEditorOnSpace = directoryProperties.isUserEditor();	
		
		// invisible files
		Vector invisibles = ChannelConfiguration.getInstance().getInvisibleRegexp(); 
		
		// for each resource, we get the state
		for (int i=0; i<resources.length; i++) {
			ChannelResource res = (ChannelResource)resources[i];		
			
			// the name of the resource
			String name = res.getName();

			// allowed ?
			boolean allowed = true;
			for (int j=0; j<invisibles.size(); j++) {
				String inv = (String)invisibles.elementAt(j);    
				
				if (name.matches(inv))                           
					allowed = false;                       
            }
			
			// if allowed to see it
			if (allowed) {
				
				// if collection
				if (res.isCollection()) {
					
					// the type: document, space ?
					String fullPath = path+name;
					String type = MetaDataManager.getDirectoryType(currentSpace, fullPath);
					
					// check the state for the document
					if (type != null) {
						if (type.equals(MetaDataConstants.INJAC_TYPE_DOCUMENT)) {
							String state = MetaDataManager.getDocumentState(currentSpace, fullPath);	
							res.setState(state);
						}
						else if (type.equals(MetaDataConstants.INJAC_TYPE_SPACE)) {
							res.setState(type);
						}
					}
					
				}
				
			}
			
			// not allowed
			else {
				resources[i] = null;
			}
		}
		
		TreeSet sortedResources = SortedChannelResource.sortResources(resources, currentSortType);
		
		// for each sorted resource, we get the xml
		Iterator iter = sortedResources.iterator();
		while(iter.hasNext()) {
			ChannelResource res = (ChannelResource)iter.next();		
			
			// the name of the resource
			String name = res.getName();
			String displayName = res.getName();
			
			// the last modified date
			Calendar lastModified = Calendar.getInstance();
			lastModified.setTimeInMillis(res.getLastModified());
			
			// if collection
			if (res.isCollection()) {
				
				// if we are in a space
				if (directoryProperties.getType().equals(MetaDataConstants.INJAC_TYPE_SPACE)) {

					// the state: document, space ?
					String state = res.getState();
					
					// no state, we show default directory
					if (state == null || state.equals("")) {
						xmlResources.append(getXmlForResource(name, displayName, "directory", "", false, "0", lastModified));
					}
					else {
							
						// if space type
						if (state.equals(MetaDataConstants.INJAC_TYPE_SPACE)) {
							xmlResources.append(getXmlForResource(name, displayName, "directory", state, false, "0", lastModified));
						}
							
						// if type document
						else {
								
							// if writer or editor on space
							if (userIsWriterOnSpace || userIsEditorOnSpace) {
								xmlResources.append(getXmlForResource(name, displayName, "directory", state, (name.equals(directoryProperties.getRootDocumentName())), "0", lastModified));
							}
						}
					}
				}
				
				// if we are not in a space
				else {
					xmlResources.append(getXmlForResource(name, displayName, "directory", "", false, "0", lastModified));
				}
									
			}
				
			// if file
			else {					
				xmlResources.append(getXmlForResource(name, displayName, res.getContentType(), null, false, getLengthFormat((long)res.getContentLength()), lastModified));					
	        }
			
		}	
		
		StringBuffer xml = new StringBuffer();
		String previewLink = currentSpace.getServer().getParameter(ServerConstants.INJAC_PREVIEW_URL);
		if (previewLink!=null) {
			if (previewLink.endsWith("/")) {
				previewLink = previewLink.substring(0, previewLink.length()-1);
			}
			String previewPath = "/";
			for (int i=1;i<currentSpace.getPathSize(); i++) {
				previewPath += currentSpace.getPathElementAt(i)+"/";
			}
			
			previewLink += previewPath;
			xml.append("<PREVIEW link=\""+previewLink+"\"/>");
		}
		xml.append("<CONTENT sort=\""+currentSortType+"\">");										
		xml.append(xmlResources);
		xml.append("</CONTENT>");

		return xml;
	}
	
	
	
	
	

	/**
	 * Return the xml for one resource
	 * @param name the name of the resource
	 * @param type the type of the resource
	 * @param state the state of a directory
	 * @param defaultDocument if it is a directory, if it is the default document
	 * @param weight the weight of the resource
	 * @param date the last modification date
	 * @return the xml for one resource
	 */
	private static StringBuffer getXmlForResource(String name, String displayName, String type, String state, boolean defaultDocument, String weight, Calendar date) {
		StringBuffer xml = new StringBuffer();
		
		xml.append("<RESOURCE ");
		
		// the label
		String label = displayName.replaceAll("&","&amp;");
		label = label.replaceAll("\"","&#148;");
		xml.append("label=\""+label+"\" ");
		
		// the link
		String link = name.replaceAll("&","&amp;");
		link = link.replaceAll("\"","&#148;");
		link = link.replaceAll("'","\\\\'");
		xml.append("link=\""+link+"\" ");
		
		// the type
		String encodedType = type;
		if (type!=null) {
			try {
				encodedType = URLEncoder.encode(type, "utf-8");
			}
			catch(UnsupportedEncodingException e) {
	
				// log
				if (log.isDebugEnabled()){
					log.debug("getXmlForResource"+" :: "+e);
				}
			}
		}
		xml.append("type=\""+encodedType+"\" ");
		

		// the state and the default
		if (type.equals("directory")) {
			
			xml.append("state=\""+state+"\" ");
			xml.append("default=\""+defaultDocument+"\" ");
			
		}
		// weight
		xml.append("weight=\""+weight+"\" ");
		
		// date
		xml.append(getLastUpdateDateXml(date)+"\n");
		
		return xml;
	}
	
	

}
