/**
 * @author Thomas Bellembois
 * @version
 * 
 * Creation date : 05 ao�t 2005
 * Last modification :
 */
package org.esupportail.injac.webdavServer.esupWDServerManager.core.quotaManager;

import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.Enumeration;

import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceException;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import fr.univrennes1.cri.util.commonUtils.CommonUtils;

public class QuotaManager {

	private static Call call;

	private static Log log;
	
	private boolean connected;
	
	public QuotaManager() {
		connected = false;
		log = LogFactory.getLog(getClass().getName());
	}
	
	public boolean connect(String webServiceURL, String userName, String password) throws 	
	MalformedURLException, 
	ServiceException, 
	RemoteException {
		
		log.debug("connect:webServiceURL="+webServiceURL+" userName="+userName);
		
		if (webServiceURL == null) {
			log.error("connect:webServiceURL can not be null");
			return false;
		}
		if (userName == null) userName = "";
		if (password == null) password = "";
		
		boolean result = false;
		
		String endpoint = webServiceURL;
		
		Service service = new Service();
		call = (Call) service.createCall();
		
		call.setUsername(userName);
		call.setPassword(password);
		call.setMaintainSession(true);
		call.setTargetEndpointAddress( new java.net.URL(endpoint) );
		
		String tmpResult = (String)call.invoke(new QName("init"), new Object[] { "none" });
		result = Boolean.valueOf(tmpResult).booleanValue();
	
		connected = true;
		
		log.debug("connect:result="+result);
		
		return result;
	}// connect

	
	public long getQuotaUsedBytes(String path) 
	throws 
	RemoteException {
		
		log.debug("getQuotaUsedBytes:path="+path);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return 0;
		}
		
		if (path == null) {
			log.error("getQuotaUsedBytes:path can not be null");
			return 0;
		}
		
		long result = 0;
		String usedBytes = null;
		
		Object object = call.invoke(new QName("getQuotaUsedBytes"), new Object[] { path });      
      	if (object != null) usedBytes = (String)object;
		if (usedBytes != null && !usedBytes.equals("null")) result = new Long(Long.parseLong(usedBytes)).longValue();	
		else result = 0;
      	
      	log.debug("getQuotaUsedBytes:result="+result);
      	
		return result;
		
	}// getQuotaUsedBytes
	
	
	public long getQuotaAvailableBytes(String path) 
	throws 
	RemoteException {
		
		log.debug("getQuotaAvailableBytes:path="+path);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return 0;
		}
		
		if (path == null) {
			log.error("getQuotaAvailableBytes:path can not be null");
			return 0;
		}
		
		long result = 0;
		String availableBytes = null;
		
		Object object = call.invoke(new QName("getQuotaAvailableBytes"), new Object[] { path });
		if (object != null) availableBytes = (String)object;
      	if (availableBytes != null && !availableBytes.equals("null")) result = new Long(Long.parseLong(availableBytes)).longValue();
		else result = 0; 
      	      	
    	log.debug("getQuotaAvailableBytes:result="+result);
		
    	return result;
		
	}// getQuotaAvailableBytes
	
	
	public boolean getVirtualRoot(String path) 
	throws 
	RemoteException {
		
		log.debug("getVirtualRoot:path="+path);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return false;
		}
		
		if (path == null) {
			log.error("getVirtualRoot:path can not be null");
			return false;
		}
		
		boolean result = false;
		String tmpVirtualRoot = null;
		
		Object object = call.invoke(new QName("getVirtualRoot"), new Object[] { path });
		if (object != null) tmpVirtualRoot = (String)object;
      	if (tmpVirtualRoot != null && tmpVirtualRoot.equals("null")) result = Boolean.valueOf(tmpVirtualRoot).booleanValue();
		else result = false;
      	
      	log.debug("getVirtualRoot:result="+result);
      	
		return result;
		
	}// getVirtualRoot
	
	
	public String getTreeQuotaInformation(String path, boolean processFiles, int maxDepth)
	throws 
	RemoteException {
		
		log.debug("getTreeQuotaInformation:path="+path+" processFiles="+processFiles);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return "";
		}
		
		if (path == null) {
			log.error("getTreeQuotaInformation:path can not be null");
			return "";
		}
		
		if (maxDepth <=0) maxDepth = 1; // 0 or less would not display anything
		
		String result = "";
	
		result = (String) call.invoke(new QName("getTreeQuotaInformation"), new Object[] { path, new Boolean(processFiles), new Integer(maxDepth) });       
		if (result == null) result = ""; // should never happen
		
		log.debug("getTreeQuotaInformation:result="+result);
		
		return result;
		
	}// getTreeQuotaInformation
		
	
	public boolean patchQuotaAvailableBytes(String path, long value)
	throws 
	RemoteException {
			
		log.debug("patchQuotaAvailableBytes:path="+path+" value="+value);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return false;
		}
		
		if (path == null) {
			log.error("patchQuotaAvailableBytes:path can not be null");
			return false;
		}
		
		boolean result = false;
		
		String tmpResult = (String) call.invoke(new QName("patchQuotaAvailableBytes"), new Object[] { path, new Long(value) });       
      	result = Boolean.valueOf(tmpResult).booleanValue();
      	
      	log.debug("patchQuotaAvailableBytes:result="+result);
      	
		return result;
		
	}// patchQuotaAvailableBytes
	
	
	public boolean patchQuotaUsedBytes(String path, long value, boolean overwrite)
	throws 
	RemoteException {
			
		log.debug("patchQuotaUsedBytes:path="+path+" value="+value+" overwrite="+overwrite);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return false;
		}
		
		if (path == null) {
			log.error("patchQuotaUsedBytes:path can not be null");
			return false;
		}
		
		boolean result = false;
		
		String tmpResult = (String) call.invoke(new QName("patchQuotaUsedBytes"), new Object[] { path, new Long(value), new Boolean(overwrite) });       
      	result = Boolean.valueOf(tmpResult).booleanValue();
      	
      	log.debug("patchQuotaUsedBytes:result="+result);
      	
		return result;
		
	}// patchQuotaUsedBytes
	
	
	public boolean setVirtualRoot(String path, boolean value)
	throws 
	RemoteException {
			
		log.debug("setVirtualRoot:path="+path+" value="+value);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return false;
		}
		
		if (path == null) {
			log.error("setVirtualRoot:path can not be null");
			return false;
		}
		
		boolean result = false;
		
		String tmpResult = (String) call.invoke(new QName("setVirtualRoot"), new Object[] { path, String.valueOf(value) });       
      	result = Boolean.valueOf(tmpResult).booleanValue();
      	
      	log.debug("setVirtualRoot:result="+result);
      	
		return result;
		
	}// setVirtualRoot
	
	
	public long calculateQuotaUsedBytes(String path)
	throws 
	RemoteException {
			
		log.debug("calculateQuotaUsedBytes:path="+path);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return 0;
		}
		
		if (path == null) {
			log.error("calculateQuotaUsedBytes:path can not be null");
			return 0;
		}
		
		int result;
		
		String tmpResult = (String) call.invoke(new QName("calculateQuotaUsedBytes"), new Object[] { path });       
      	result = Integer.parseInt(tmpResult);
      	
      	log.debug("calculateQuotaUsedBytes:result="+result);
      	
		return result;
		
	}// patchQuotaUsedBytes
	
	
	public boolean setQuota(String path, long quota, int depth, boolean calculateQuotaUsedBytes)
	throws 
	RemoteException {
	
		log.debug("setQuota:path="+path+" quota="+quota+" depth="+depth+" calculateQuotaUsedBytes="+calculateQuotaUsedBytes+"\n");
		
		if (!connected) {
			log.info("You are not connected to the Web service !"+"\n");
			return false;
		}
		
		if (path == null) {
			log.error("setQuota:path can not be null"+"\n");
			return false;
		}
		
		boolean result = true;
		
		Enumeration children = CommonUtils.convertStringToEnumeration(getChildren(path, false, depth), ":");
		
		while (children.hasMoreElements()) {
			String child = (String) children.nextElement();
			log.debug("setQuota:child="+child+"\n");
			String tmpResult = (String) call.invoke(new QName("setQuota"), new Object[] { child, new Long(quota), new Boolean(calculateQuotaUsedBytes) });       
			result = result && Boolean.valueOf(tmpResult).booleanValue();
		}
      	
      	log.debug("setQuota:result="+result+"\n");
      	
		return result;
		
	}// setQuota
	
	
	public boolean removeQuota(String path, boolean processChildren)
	throws 
	RemoteException {
	
		log.debug("removeQuota:path="+path+" processChildren="+processChildren);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return false;
		}
		
		if (path == null) {
			log.error("removeQuota:path can not be null");
			return false;
		}
		
		boolean result = false;
		
		String tmpResult = (String) call.invoke(new QName("removeQuota"), new Object[] { path, new Boolean(processChildren) });       
      	result = Boolean.valueOf(tmpResult).booleanValue();
		
      	log.debug("removeQuota:result="+result);
      	
		return result;
		
	}// setQuota
	

	public String getChildren(String path, boolean processFiles, int depth)
	throws 
	RemoteException {	
		
		log.debug("getChildren:path="+path+" processFiles="+processFiles+" depth="+depth);
		
		if (!connected) {
			log.info("You are not connected to the Web service !");
			return "";
		}
		
		if (path == null) {
			log.error("getChildren:path can not be null");
			return "";
		}
			
		String result = "";
		
		String childrenString = "";
		if (depth !=0) childrenString = (String) call.invoke(new QName("getChildren"), new Object[] { path, new Boolean(processFiles) });       
		
		if (depth == 0) result = ":"+path;
		else if (!childrenString.equalsIgnoreCase("")){
			Enumeration childrenEnum = CommonUtils.convertStringToEnumeration(childrenString, ":");
			
			while (childrenEnum.hasMoreElements()) {
				String childrenName = (String) childrenEnum.nextElement();
				if (!path.equalsIgnoreCase("/"))result += getChildren(path+"/"+childrenName, processFiles, depth-1);
				else result += getChildren(path+childrenName, processFiles, depth-1);
			}// while (childrenEnum.hasMoreElements())
		}
		
		log.debug("getChildren:result="+result);
		
		return result;
		
	}// getChildren

}
