/*
 * Created on 19 mai 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package org.injac.indexing.util;


import org.apache.commons.httpclient.HttpURL;
import org.apache.webdav.lib.methods.DepthSupport;
import org.apache.webdav.lib.methods.PropFindMethod;
import org.apache.webdav.lib.WebdavResource;
import org.apache.webdav.lib.WebdavFile;
import org.injac.indexing.Consts;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.Enumeration;
import org.apache.webdav.lib.Property;
import org.apache.commons.httpclient.util.URIUtil;
import org.apache.commons.httpclient.URIException;
import org.apache.log4j.Logger;
import org.apache.webdav.lib.ResponseEntity;
import org.injac.indexing.exceptions.ExtractMetadataException;

import java.util.HashMap;

/**
 * @author Marius Mirea, Francois Jannin
 * Classe permetant l'extraction des metadonnees inJac
 * d'un fichier inJac
 */
public class MetadataExtract {
	static Logger logger = Logger.getLogger("INJAC_INDEX");
	static final String NAMESPACES = "INJAC:";
	// md date in format 2006-04-13T08:23:09Z
	static final String MD_LASTMODIFIED ="D:modificationdate";
	protected WebdavFile webdavFile=null;
	protected WebdavConnection webdavConnection;
	/**
	 * 
	 */
	public MetadataExtract(WebdavConnection webdavConnection) {
		super();
		this.webdavConnection = webdavConnection;
		
	}
	
	
	/**
	 * Main method for metadata extraction - extract all INJAC: namespace metadatas
	 * plus modificationdate for update managing
	 * @return	String[]
	 * @throws ExtractMetadataException
	 */
	public HashMap getMetadata(WebdavFile webdavFile) throws ExtractMetadataException{
		if(webdavFile==null){
			logger.error("webdavFile null");
			return null;
		}
		this.webdavFile = webdavFile;
		WebdavResource parent = getParent();
		
		
		HashMap metadatas = new HashMap();
		
		Enumeration result;
		Enumeration current;
		ResponseEntity item;
		Property p;
		String path = getParentUrl();
		path = checkPath(path);
				
		try
		{
			PropFindMethod method = new PropFindMethod(path);
			parent.retrieveSessionInstance().executeMethod(method);
			result = method.getResponses();
			while(result.hasMoreElements()){
				item = (ResponseEntity)result.nextElement();
				current = item.getProperties();
				while(current.hasMoreElements()){
					p = (Property)current.nextElement();
					String s = p.getNamespaceURI();
					if(NAMESPACES.indexOf(s) != -1){
						String value = URLDecoder.decode(p.getPropertyAsString(), "UTF-8");
						//String value = p.getPropertyAsString();
						metadatas.put(p.getName(),value );
					}
					else if(p.getName().equals(MD_LASTMODIFIED)){
						String value = URLDecoder.decode(p.getPropertyAsString(), "UTF-8");
						metadatas.put(p.getName(),value);
					}
					
				}
			}
		}
		catch(Exception e)
		{
			logger.error("Exception : "+e.getLocalizedMessage());
		}
		// add namespace from INJAC:injac
		
		String metas = getSpaceMetadatas(webdavFile);
		if((metas!=null) && !metas.equals("")){
			ParseRequiredMetaData parser = new ParseRequiredMetaData(metas);
			String value = parser.getNamespace();
			if(value==null){
				value=Consts.NONAMESPACE;
			}
			metadatas.put(Consts.INDEX_NAMESPACE, value);
		}else
		{
			metadatas.put(Consts.INDEX_NAMESPACE, Consts.NONAMESPACE);
		}
		return metadatas;
	}
	
	
	protected String checkPath(String path)
	{
		
		String realPath = path;
		try{
		
		if (path.endsWith("/")) {
			realPath = realPath.substring(0, realPath.length()-1);
		}	
		
		realPath = URIUtil.encodePathQuery(realPath);
		//realPath = realPath.replaceAll(" ","%20");
		realPath = realPath.replaceAll("!","%21");			
		realPath = realPath.replaceAll("#","%23");
		realPath = realPath.replaceAll("\\$","%24");					
		realPath = realPath.replaceAll("&","%26");
		realPath = realPath.replaceAll("'","%27");
		realPath = realPath.replaceAll("\\(","%28");
		realPath = realPath.replaceAll("\\)","%29");		
		realPath = realPath.replaceAll("@","%40");		
		realPath = realPath.replaceAll("`","%60");
		}catch(Exception e)
		{
			System.out.println("Exc");
		}
			
		return realPath;
	}
	
	protected WebdavResource getParent(){
	 	
		WebdavResource wdr = null;
		String parent = getParentUrl();
		
	 	try{
			HttpURL hrl = new HttpURL(parent);
			hrl.setUserinfo(webdavFile.getUser(),webdavFile.getPass());
			wdr = new WebdavResource(hrl);
			}
		catch(URIException urie){
			urie.printStackTrace();
			}
		catch(IOException ioe){
			ioe.printStackTrace();
			}
		
		return wdr;
		}
	
	protected String getParentUrl(){
		String name = webdavFile.getName();
		String path = webdavFile.getAbsolutePath();
		String parent = path.substring(0, 
				path.length() - name.length() - 1);
		return parent;
		}
	protected String getSpaceMetadatas(WebdavFile webdavFile){
		String path = getSpaceParentUrl(getParentUrl());
		return getSpaceMetadatas(path);
	}
	
	protected String getSpaceMetadatas(String path){
		
		int index = path.indexOf("/slide/");
		// no slide context case
		if(index==-1)
			index = path.indexOf("/files");
		
		String ppath = path.substring(index);
		
		
		path = checkPath(path);
		java.util.Vector vprop= new java.util.Vector();
		vprop.add("INJAC:document-injac-metadata");
		try{
			Enumeration props = webdavConnection.getProperties(ppath, DepthSupport.DEPTH_0, vprop);
			Property prop =(Property)props.nextElement();
			String meta = URLDecoder.decode(prop.getPropertyAsString(), "UTF-8");
			// recursive search of a parent with metas
			if(meta.equals("")){
				if(path.lastIndexOf('/')>1){
					return getSpaceMetadatas(path.substring(0,path.lastIndexOf('/')));
				}
			}
			return meta;
		}catch(Exception e){
			logger.error("unable to get metadata from "+webdavFile.getPath());
			return null;
		}
	}
	protected String getSpaceParentUrl(String docPath){
		
		String result = docPath.substring(0, docPath.lastIndexOf('/'));
		return result;
	}	
	
}
