package com.bea.hross.dr;

import com.plumtree.dr.DocumentRepository;
import com.plumtree.dr.ActiveDocument;
import com.plumtree.dr.RepositoryException;
import com.plumtree.dr.ArchivedDocument;

import com.plumtree.dr.util.config.XConfig;
import com.plumtree.dr.util.crypto.CryptoUtil;

import com.plumtree.dr.hessian.HessianClientFactory;

import java.io.*;
import java.util.Map;
import java.util.HashMap;

public class RepositoryDemo {

	// file upload buffer size
	private static int BUFFER_SIZE = 32768;
	
	// the repository for this application
	private static DocumentRepository _repository;
	
	// these are static variables for our fake application
	private static String _applicationName = "";
	private static String _applicationPassword = "";
	private static String _configurationDirectory = "";
	
	// toy method to demonstrate dr capabilities
	public static void main(String[] args) {
		System.out.println("******************************************");
		System.out.println("A simple document repository test application.");
		System.out.println("  by H. Ross Brodbeck, BEA Systems Inc");
		System.out.println("");
		System.out.println("");
		System.out.println("No warranty is provided with this application. It is not even");
		System.out.println("guaranteed to function. I am sure there are bugs. Use it at your own risk.");
		System.out.println("");
		System.out.println("******************************************");
		System.out.println("");
		
		// here's where we set up the repository
		String password = "password";
		setConfigurationDirectory("C:/sandbox/drtest/");
		setApplicationName("pthack");
		setApplicationPassword(password);
		
		System.out.println("A test of DR encryption:");
		System.out.println("Password is: " + password);
		String encrypted = CryptoUtil.encrypt(password);
		System.out.println("Encrypted password is: " + encrypted);
		System.out.println("Decrypted password is: " + CryptoUtil.decrypt(encrypted));
		System.out.println("");
		
		// and the upload file
		String testFile = "C:/sandbox/drtest/dummy_text.txt";
		
		System.out.println("Testing document upload: (uploading " + testFile + ")");
		String docId = uploadDocument(testFile);
		System.out.println("Uploaded ID is: " + docId);
		System.out.println("");
		
		if (docId.length() <= 0) return;
		
		System.out.println("Archiving document...");
		String arcId = archiveDocument(docId);
		System.out.println("Archived ID is: " + arcId);
		System.out.println("");
		
		if (arcId.length() > 0) {
			System.out.print("Deleting archive...");
			deleteDocument(arcId);
			System.out.println("Success!");
			System.out.println("");
		}
		
		System.out.print("Deleting document...");
		deleteDocument(docId);
		System.out.println("Success!");	
		System.out.println("");
		
		System.out.println("Document repository test completed. Exiting...");
	}	

	/***
	 * Create a remote repository object based on some configuration information.
	 * @param configDirectory - The directory in which dr.xml resides.
	 * @param applicationName - The application name. Should be the same as in dr.xml.
	 * @param password - The application password. Should be the same as in dr.xml (unencrypted, though).
	 * @return A remote document repository object.
	 * @throws Exception
	 */
	private static DocumentRepository createRepository(String configDirectory, String applicationName, String password) {
		try {
			// create a new configuration based on dr.xml
			String drConfigLocation = configDirectory + "dr.xml";
			Map properties = new HashMap(3);
			XConfig config = new XConfig(drConfigLocation);
		
			// load information from server.properties
			properties.put("application/name", applicationName);
			properties.put("application/password", password);
			properties.put("config", config);
		
			// create the dr from hessian
			// (an open source binary web service protocol)
			// http://www.caucho.com/hessian/
			HessianClientFactory hessianFactory = new HessianClientFactory();
			return hessianFactory.getInstance(properties);
		} catch (Exception ex) {
			return null;
		}
	}

	
	public static void setApplicationName(String applicationName) {
		_applicationName = applicationName;
	}
	
	public static void setApplicationPassword(String applicationPassword) {
		_applicationPassword = applicationPassword;
	}
	
	public static void setConfigurationDirectory(String configurationDirectory) {
		_configurationDirectory = configurationDirectory;
	}
	
	/***
	 * Get an instance of a remote repository, given configuration settings.
	 * @return
	 */
	private static DocumentRepository getRepository() {
		if (null != _repository) return _repository;
		_repository = createRepository(_configurationDirectory, _applicationName, _applicationPassword);
		return _repository;
	}
	    
    /***
     * Download a document from the document repository.
     * @param id
     * @param path
     * @throws RepositoryException
     * @throws IOException
     */
    public void downloadDocument(String id, String path) throws RepositoryException, IOException {
    	ActiveDocument a = (ActiveDocument) _repository.getDocument(id);
    	FileOutputStream fs = new FileOutputStream(path, false);
    	a.getContents(fs);
    }
    
    /***
     * Archive a document in a document repository
     * @param id
     * @return
     */
    public static String archiveDocument(String id) {
    	try {
    		ArchivedDocument doc = (ArchivedDocument) getRepository().archiveDocument(id);
    		return doc.getId();
    	} catch (Exception ex) {
    		return "";
    	}
    }
    
    /***
     * Delete a document from the repository.
     * @param repository
     * @param id
     */
    public static void deleteDocument(String id) {
    	try { 
    		getRepository().deleteDocument(id);
    	} catch (Exception ex) {
    	}
    }
    
    /***
     * Store a document in a document repository.
     * @param filePath
     * @param contentType
     * @return
     * @throws IOException
     */
    public static String uploadDocument(String filePath) {
    	
        // temporary buffer for the file, number of bytes written
        long numBytes = 0;
        byte buf[] = new byte[BUFFER_SIZE];
        
        // create a new active document in the repository
        ActiveDocument doc = getRepository().createActiveDocument();

        OutputStream target = null;
        try {
        	target = doc.openOutputStream(-1);
        } catch (RepositoryException rex) {
        	// document repository failed to open an output stream for the document
        	return "";
        }
        
        try {
        	// here's where we open an input stream to provide a file
        	InputStream source = new FileInputStream(filePath);
        
        	// write the file using the DR as our target
        	int i = 0;
        	while(-1 != (i = source.read(buf))) {
            	target.write(buf, 0, i);
            	numBytes += i;
        	}
        
        	// close out our sources
        	if (null != source) source.close();
        	if (null != target) target.close();
        	if (null != source) source.close();
        
        } catch (Exception ex) {
        	return "";
        }
        
        // get info from the uploaded document
        String id = doc.getId();
        if(0 == doc.getSize()) { 
        	try {
        		doc.delete(); // no document uploaded, so delete it
        	} catch (RepositoryException rex) {
        		// something bad happened here
        	}
        	return "";
        } 

        return id;
    }
}
