/**
 * Copyright (c) Artenum SARL 2004-2005
 * @author Julien Forest / Sebastien Jourdain
 *
 * All rights reserved. This software can
 * not be used or copy or diffused without
 * an explicit license of Artenum SARL, Paris-France
 */
package com.artenum.cassandra.plugin.cloud;

import java.awt.Frame;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.swing.JPopupMenu;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.MultipartPostMethod;

import vtk.vtkX3DExporter;

import com.artenum.cassandra.pipeline.Filter;
import com.artenum.cassandra.pipeline.PipeLineManager;
import com.artenum.cassandra.plugin.CassandraPlugInProperty;
import com.artenum.cassandra.plugin.CassandraPlugin;
import com.artenum.cassandra.plugin.PlugInControlUI;
import com.artenum.cassandra.plugin.PluginManager;
import com.artenum.mail.ScriptedMultiMailer;

/**
 * <pre>
 * <b>Project ref           :</b> CASSANDRA project
 * <b>Copyright and license :</b> See relevant sections
 * <b>Status                :</b> under development
 * <b>Creation              :</b> 04/03/2005
 * <b>Modification          :</b>
 *
 * <b>Description  :</b>
 *             This class defines the VTK processing pipeline itself
 *             and the initialisation of the contextual GUI of the plugin.
 *
 * </pre>
 * <table cellpadding="3" cellspacing="0" border="1" width="100%">
 * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor"><td><b>Version number</b></td><td><b>Author (name, e-mail)</b></td><td><b>Corrections/Modifications</b></td></tr>
 * <tr><td>0.1</td><td>Julien Forest, j.forest@artenum.com</td><td>Creation</td></tr>
 * </table>
 *
 * @author        Julien Forest
 * @version       1.2
 */
@SuppressWarnings("deprecation")
public class CloudPlugin implements CassandraPlugin{
    private String name;
    private Frame owner;
    private PipeLineManager pipelineManager;
    private PluginManager pluginManager;
    
    private Filter filterImpl;
    
    private long tmpCurrentTime = -1;
    private String sessionName = "none";
    private File tempX3DFile = null;

    private HttpClient client = null;
    
    //http://81.57.18.42:8080/CassandraCloud/
	//private String baseUrl = "http%3A%2F%2F81.57.18.42%3A8080%2FCassandraCloud";
	//private String baseUrl = "http://81.57.18.42:8080/CassandraCloud";
	private String baseUrl = "http://localhost:8080/CassandraCloud";
	private String currentUrl = "";
	
	private String managerAddress = null;
	private List guestList;
	
	public static final String SERVER_ADDRESS = "com.artenum.cloud.server.address";
	
	private ScriptedMultiMailer sender;
	private Properties settings;
	
	private boolean sendMailFlag = true;
	
    
    public CloudPlugin() {
        this.name = "3D Exporter Plugin";
    }

    public CloudPlugin(PipeLineManager pipelineManager, PluginManager pluginManager, Frame owner) {
        this();
        this.pipelineManager = pipelineManager;
        this.pluginManager = pluginManager;
        this.owner = owner;   
        guestList = new ArrayList<String>();
        
        this.sender = new ScriptedMultiMailer();
        this.settings = sender.readSettings("./resources/cassandraCloudSettings.properties");
        
        System.out.println( this.settings.entrySet().toString());
        
        if(System.getProperty(this.SERVER_ADDRESS) == null){
        	System.out.println("Server address in configuration file: " + this.settings.getProperty(this.SERVER_ADDRESS));
        	if(this.settings.getProperty(CloudPlugin.SERVER_ADDRESS) != null){
        	    this.baseUrl = "http://" + this.settings.getProperty(CloudPlugin.SERVER_ADDRESS);
        	    System.getProperties().put(this.SERVER_ADDRESS, this.baseUrl);
        	} else {
        		this.baseUrl = "Error: server not defined";
        	}
        } else {
        	this.baseUrl = System.getProperty(this.SERVER_ADDRESS);
        }
    }

    
    /**
     * Perform the action, i.e load the stuff on the Cloud and connect to the session  
     */
    public void update() {
    	
		//connection to the server
		this.client = new HttpClient(); 
		
		//establish a connection within 5 seconds
		this.client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); 
		
		CloudControlUI pluginUI = new CloudControlUI( this, owner);
		pluginUI.setLocationRelativeTo(null);
		pluginUI.setVisible(true);
    }

    /**
     * Connect to the session and launch a Java Web Start based independent client. 
     * 
     * @return
     */
    public String connectToSession(){
		// session connection
		currentUrl = baseUrl + "/V3D.jsp?scene=dynamic&etude=" + this.sessionName;
		System.out.println(currentUrl);
		//String result = performHttpGetMethod(client, currentUrl);
		
		//to start the Java Web start client here ? NASTY
		try {
			Runtime.getRuntime().exec("javaws " +  currentUrl);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return(currentUrl);
    }
    
    /**
     * Create the shared session
     * @return
     */
    public String createSharedSession(){
    	// session creation
		currentUrl = baseUrl + "/action/create/?etude=" + sessionName + "&sceneURL=" + baseUrl + "%2Fscene3d%2F" + tempX3DFile.getName();
		System.out.println(currentUrl);
		return(performHttpGetMethod(client, currentUrl));
    }
    
    /**
     * Upload the 3D scene.
     * @return
     */
    @SuppressWarnings("deprecation")
	public String uploadScene(){
    	this.tmpCurrentTime = System.currentTimeMillis();
    	this.sessionName = String.valueOf(tmpCurrentTime);
    	
    	// generation of the X3d scene
    	try {
			tempX3DFile = File.createTempFile(sessionName, ".x3db" );
			this.export(tempX3DFile.getAbsolutePath());
			System.out.println(tempX3DFile.getAbsolutePath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// scene upload
		//currentUrl = baseUrl + "/Browser.jsp?first&uplMonitor=" + tempX3DFile.getName();
		//System.out.println(currentUrl);
		//return(performHttpGetMethod(client, currentUrl));
		
		
		// Create POST method
		currentUrl = baseUrl + "/file";
		System.out.println(currentUrl);
		MultipartPostMethod method = new MultipartPostMethod( currentUrl );
		try {
			method.addParameter(tempX3DFile.getName(), tempX3DFile );
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		//method.addPart( new FilePart( "sample.txt", file2, "text/plain", "ISO-8859-1" ) ); 
		
		// Execute and print response
		try {
			client.executeMethod( method );
		} catch (HttpException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		String response = null;
		try {
			response = method.getResponseBodyAsString( );
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		//System.out.println( response );
		method.releaseConnection( );
		return(response);
    }
    
    
    private String performHttpGetMethod(HttpClient client, String url){
    	
		HttpMethod method = null;
		String responseBody = null;
    	
		//create a method object
		method = new GetMethod(url);
		method.setFollowRedirects(true);
		
		//execute the method
		try{
		    client.executeMethod(method);
		    responseBody = method.getResponseBodyAsString();
		} catch (HttpException he) {
		    System.err.println("Http error connecting to '" + url + "'");
		    System.err.println(he.getMessage());
		    //System.exit(-4);
		} catch (IOException ioe){
		    System.err.println("Unable to connect to '" + url + "'");
		    //System.exit(-3);
		}
		return responseBody;
    }
    
    /**
     * Export the scene to an X3D file using the VTK 5.XX exporter. 
     * @param fileX3D
     */
    public void export(String fileX3D) {
    	 System.out.println("Exporting to X3D...");
    	 vtkX3DExporter exporter = new vtkX3DExporter();
    	 
         System.out.println(fileX3D);
         exporter.SetFileName(fileX3D);
		 System.out.println("BINARY EXPORT");
		 exporter.BinaryOn();
         exporter.SetInput(pipelineManager.getCassandraView().GetRenderWindow());
		 
         exporter.Update();
         exporter.Write();
         System.out.println("DONE");
    }

    /**
     * return the name of the current plugin. 
     */
    public String getName() {
        return name;
    }

    /**
     * Sent fh invitation of guest users. 
     */
    public void sendInvitations(){
    	
		sender.setSmtpHost(settings.getProperty(ScriptedMultiMailer.SMTP_SERVER));
		System.out.println("SMTP server:" + sender.getSmtpHost());
		
		//if ( settings.getProperty(ScriptedMultiMailer.ACTIVATE_SENDING_FLAG) != null){
		//    sender.setActivate_sending(Boolean.valueOf( settings.getProperty(ScriptedMultiMailer.ACTIVATE_SENDING_FLAG)));
		//}

		
		sender.setActivate_sending(this.sendMailFlag);
				
        sender.setFrom(this.managerAddress);

	    String subject  = "Invitation to Cassandra Cloud's session: " + this.sessionName;
	    
	    String currentUrl = baseUrl + "/V3D.jsp?scene=dynamic&etude=" + this.sessionName;
	    String content = "      Cassandra Cloud Experimental Service \n \n"
	    		         + "You are invited by " + this.managerAddress + " to visualise and shared \n"
	    		         + "3D scientific results or a virtual reality scene. \n \n "
	    		         + "Please click on the following link to access to the shared 3D scene: " + "\n"
	                     + currentUrl +"\n \n"
	                     + "This link requiers Java Web Start unable on your local machine. If the \n"
	                     + "JWS based client does not start, please go to the Cassandra Cloud site for \n"
	                     + "further information (see " + this.baseUrl + "). \n"
	                     + "\n \n"
	                     + "Cassandra Cloud is an experimental service of the Artenum Company (www.artenum.com).";
	    
	    System.out.println("Guest list:");
	    Iterator<String> iter = this.guestList.iterator();
	    while(iter.hasNext()){
	    	System.out.println(iter.next());
	    }
	    
	    try{
	    	sender.sendMesssage(this.guestList, null, null, subject, content);    
	    }catch (Exception e) {
			System.out.println("Impossible to sent invitation emails");
			e.printStackTrace();
		}
	    
    }


    public String toString() {
        return getName();
    }

	@Override
	public JPopupMenu getContextualMenu() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void remove() {
		// TODO Auto-generated method stub
		
	}

    public Filter getInternalFilter() {
        return filterImpl;
    }

    /**
     * return null having no GUI control panel defined. 
     */
    @Override
    public PlugInControlUI getControlUI() {
        return null;
    }

    @Override
    public CassandraPlugInProperty getPlugInProperty() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void initAndUpdate(CassandraPlugInProperty prop) {
        // TODO Auto-generated method stub
        
    }

	public String getBaseUrl() {
		return baseUrl;
	}

	public void setBaseUrl(String baseUrl) {
		this.baseUrl = baseUrl;
	}

	public String getSessionName() {
		return sessionName;
	}

	public List getGuestList() {
		return guestList;
	}

	public void setGuestList(List guestList) {
		this.guestList = guestList;
	}

	public String getManagerAddress() {
		return managerAddress;
	}

	public void setManagerAddress(String managerAddress) {
		this.managerAddress = managerAddress;
	}

	public boolean isSendMailFlag() {
		return sendMailFlag;
	}

	public void setSendMailFlag(boolean sendMailFlag) {
		this.sendMailFlag = sendMailFlag;
	}

}
