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

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.provider.ChannelResource;
import org.esupportail.portal.channels.CStockage.provider.SortedChannelResource;

import org.esupportail.portal.channels.CStockage.channelAction.AbstractDefaultRenderXml;
import org.esupportail.portal.channels.CStockage.channelAction.classic.sharing.SharingTool;
import org.esupportail.portal.channels.CStockage.config.ChannelConfiguration;
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.ChannelException;
import org.esupportail.portal.channels.CStockage.provider.access.ServerAccess;

/** 
 * Id: DefaultRenderXml.java,v1.0 24 sept. 2004<br/>
 * Copyright (c) 2004 Esup Portail (www.esup-portail.org)<br/>
 * Classes: DefaultRenderXml<br/>
 * Original Author: Yohan Colmant<br/>
 * 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 into the channel
	 * @param currentSpace the current space used
	 * @param error the error exception
	 * @param information this information message
	 * @param sharingTool the sharing tool for the current directory
	 * @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, SharingTool sharingTool, 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, sharingTool));			
				
				// 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) {				
					erreurInterne = e.getErrorCode();

					// log
					if (log.isDebugEnabled()){
						log.debug("getXml"+" :: erreurInterne = "+erreurInterne);
					}
				}			
				catch(NotExistsResourceException e) {				
					erreurInterne = e.getErrorCode();

					// log
					if (log.isDebugEnabled()){
						log.debug("getXml"+" :: erreurInterne = "+erreurInterne);
					}
				}
				// the quota
				if (currentSpace.showQuota())
					xml.append(getXmlQuota(currentSpace));
				
				// the content of the directory	
				xml.append(getXmlContent(ressources, currentSortType));			
							
			}
			catch(ChannelException e) {			
				erreurInterne = e.getErrorCode();

				// log
				if (log.isDebugEnabled()){
					log.debug("getXml"+" :: erreurInterne = "+erreurInterne);
				}
			}		
			
			// 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 {

			// log
			if (log.isDebugEnabled()){
				log.debug("getXml"+" :: currentSpace = "+currentSpace);
			}
			
			return getXmlError(new AnyVisibleSpaceException(), -1);
		}
	}
	
	
	
	

	
	
	
	
	
	/**
	 * Get the XML for the action bar
	 * @param currentSpace current channel path
	 * @param sharingTool the sharing tool for the current directory
	 * @return the XML as a StringBuffer
	 * @throws PropertiesException
	 */
	private static StringBuffer getXmlAction(Space currentSpace, SharingTool sharingTool) throws PropertiesException {
		StringBuffer xmlTemp = new StringBuffer();
		
		xmlTemp.append("<ACTIONS>");
		
		if (currentSpace.getPathSize()>1) {
			xmlTemp.append("<PARENT>"+true+"</PARENT>");
		}
		xmlTemp.append("<REFRESH>"+true+"</REFRESH>");
		xmlTemp.append("<COPY>"+true+"</COPY>");
		
		boolean userCanWrite = currentSpace.getCurrentViewer().getUser().getPersonalization().getWriting()==1;
		if (userCanWrite) {
			xmlTemp.append("<DIRECTORY>"+true+"</DIRECTORY>");
			xmlTemp.append("<UPLOAD>"+true+"</UPLOAD>");		
			xmlTemp.append("<MOVE>"+true+"</MOVE>");
			xmlTemp.append("<PASTE>"+true+"</PASTE>");
			xmlTemp.append("<RENAME>"+true+"</RENAME>");
			xmlTemp.append("<DELETE>"+true+"</DELETE>");
		}
		
		if (currentSpace!=null) {
			boolean allowsSharing = currentSpace.allowsSharing();
			xmlTemp.append("<SHARE stillShared=\""+true+"\">"+allowsSharing+"</SHARE>");
			
			boolean showUrlInMenu = currentSpace.isBrowserAccessUrlVisibilityMenu();
			xmlTemp.append("<URL>"+showUrlInMenu+"</URL>");
		}
		
		xmlTemp.append("</ACTIONS>");
		
		return xmlTemp;		
	}
	
	
	/**
	 * Get the XML for the content
	 * @param resources all the ChannelWebdavResource objects
	 * @param currentSortType The current and default sort type for the resources
	 * @return the XML as a StringBuffer
	 * @throws PropertiesException
	 */
	private static StringBuffer getXmlQuota(Space space) {

		long[] quota = space.getServerAccessObject().getQuota(space.getCurrentPath());
		
		if (quota==null) 
			return new StringBuffer();
		
		// get the values
		long available = quota[0];
		long total = quota[1];
		
		String level = "";
		String useS = "";
		String totalS = "";
		String availableS = "";
		
		// if we don't know the total bytes of the space
		if (total==0) {
			availableS = getLengthFormat(available);
		}
		
		else {
		
			long use = total - available;
			
			long tiers = total/3;
			if (use>0 && use<tiers) {
				level = "low";
			}
			else if (use>=tiers && use<tiers*2) {
				level = "medium";
			}
			else if (use>2*tiers) {
				level = "high";
			}
			
			long usePercent = (use*100)/total;
			if (usePercent>100) {
				usePercent = 100;
			}
			useS = usePercent+"";
			totalS = getLengthFormat(total);
		}
		
		
		StringBuffer xml = new StringBuffer();
		xml.append("<quota use=\""+true+"\" level=\""+level+"\">");
		xml.append("<use>"+useS+"</use>");
		xml.append("<total>"+totalS+"</total>");
		xml.append("<available>"+availableS+"</available>");
		xml.append("</quota>");
		return xml;
		
	}
	
	
	
	
	/**
	 * Get the XML for the content
	 * @param resources all the ChannelWebdavResource objects
	 * @param currentSortType The current and default sort type for the resources
	 * @return the XML as a StringBuffer
	 * @throws PropertiesException
	 */
	private static StringBuffer getXmlContent(ChannelResource[] resources, String currentSortType) throws PropertiesException {

		// we sort the resources
		TreeSet sortedResources = SortedChannelResource.sortResources(resources, currentSortType);
		
		
		StringBuffer xmlResources = new StringBuffer();
		
		// invisible files
		Vector invisibles = ChannelConfiguration.getInstance().getInvisibleRegexp(); 

		// for each resource
		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());
			
			// 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()) {
					
					xmlResources.append(getXmlForResource(name, displayName, "directory", "0", lastModified));
				}
				
				// if file
				else {					
					xmlResources.append(getXmlForResource(name, displayName, res.getContentType(), getLengthFormat((long)res.getContentLength()), lastModified));					
	           }
				
			}			
		}		
		
		
		StringBuffer xml = new StringBuffer();
		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 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 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;");
		String linkHTML = link;
		link = link.replaceAll("'","\\\\'");
		xml.append("link=\""+link+"\" ");
		xml.append("linkHTML=\""+linkHTML+"\" ");
		
		// 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+"\" ");
		
		// weight
		xml.append("weight=\""+weight+"\" ");
		
		// date
		if (date!=null)
			xml.append(getLastUpdateDateXml(date));
		
		return xml;
	}
	
	
}
