// Example Plugin
// James Walkerdine 2004

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;

// simple example plugin that allows users to download a document from another peer
public class ExamplePlugin extends JFrame implements PluginInterface
{

	int PluginID = 10;  // the ID for this plugin
	private ClientFramework parent;


	// *********************************
	// PLUG-IN METHODS
	// *********************************
	// method to return the plugins' ID 
	public int GetPluginID()
	{
		return PluginID;
	}
	
	// method to return the name of the plugin
	public String GetPluginName()
	{
		return new String("Simple Example Plugin");
	}
	
	// method to return the description of the plugin
	public String GetPluginDescription()
	{
		return new String("Simple plugin that allows users to download files");
	}
	
	// method to return the author of the plugin
	public String GetPluginAuthor()
	{
		return new String("James Walkerdine (C) 2004");
	}
	
	// method to return the media types this module is interested in
	public int[] GetMediaInterested()
	{
		// the values returned are the ID's of the MediaTypes that the plugin handles
		// in this case the plugin only handles Document MediaTypes (ID = 5)
		int interested[] = {5}; 
		return interested;
	}
	
	// method to return contact list options for this plugin
	// i.e. what (if any) menu options will appear for this plugin over the contact list
	public Vector GetContactInterested()
	{
		Vector v = new Vector();
		v.add("Get Document");
	
		return v;
	}
	
	// method to return the icon for this plugin
	public Image GetPluginIcon()
	{
		// load in the image and then return it
		MediaTracker mt = new MediaTracker(this);
		
		Image im = this.getToolkit().getImage(parent.GetPluginsPath() + "ExamplePlugin/Icon.gif");
		
		try
		{
			mt.addImage(im, 0);
			mt.waitForAll();
		}
		catch (Exception e) {e.printStackTrace(); }
		
		if (im == null)
			System.out.println("No image");
		
		return im;
	}
	
	// method called when a user clicks on the "Get Document" action from the contact list
	public void ActivatePlugin(Integer id, String action, UserObject Participant)
	{
		// a useful check to make sure that the right plugin is being activated
		if (id.intValue() != GetPluginID())
			return;
		
		// check to see if the target is user is 'off-line'. Can't download the document if this is the case!
		if (Participant.GetStatus().equalsIgnoreCase("off-line"))
		{
			JOptionPane.showMessageDialog(null, "Unable to perform request as " + Participant.GetNickname() + " is offline","User off-line error", JOptionPane.WARNING_MESSAGE);						
			return;
		}
		
		// now check to see if it is the 'Get Document' command, and if so, act on it
		if (action.equals("Get Document"))
		{
			// make a transfer request. The framework deals with the actual transfer
			parent.MakeTransferRequest("Test.txt", GetPluginID(),      Participant.GetID(),  GetPluginID(),	     true, 					false);
			//		            filename   id of this plugin   user id of source     source plugin id    set download status dialog boxes visible   the specified path is not absolute
			
			// any transfer is done asynchronously, so plugin does not wait
			
			// we will quickly send a message to the target peer though (the one we are downloading the file from)
			// first create the hashmap that will store the message parts
			HashMap messageparts = new HashMap();
						
			Hashtable ua = parent.GetUser().GetAttributes();

			// create the message elements. These HAVE to be Strings
			messageparts.put("PLUGINID", String.valueOf(PluginID));		// We will provide the ID of the Plugin that is sending this message (this also represnts the target Plugins ID)
			messageparts.put("TYPE", "FILEREQUESTMESSAGE");  		// Simple way of determining the type of message	
			messageparts.put("SENDERID", (String) ua.get("UniqueID"));  	// Our Unique ID so the target knows who it is from
			messageparts.put("SENDERNICK", (String) ua.get("Nickname"));  	// Our Nickname so the target knows who is is from
			messageparts.put("MESSAGE", "Just getting a file off you!!");	// The message we are sending to the target
				
			// we now get the framework to send the message
			long messid = parent.SendMessage(Participant.GetPipeAd(), 	     messageparts, 					this);
			//		    		  Pipe advert of target,   the hashmap containing the message,  what component is interested (not really used - so 'this' is fine)
	
			// again message sending is asynchronous
			
			JOptionPane.showMessageDialog(null, "ExamplePlugin: ID of Sent Message" + messid, "Sent Message ID", JOptionPane.WARNING_MESSAGE);						
		}
	}
	
	// this method does not apply to this plugin
	public void ActivatePlugin(UserObject user)
	{ return; }
	
	// method to activate the plugin based on being given a specific resource object
	public void ActivatePlugin(Vector results)
	{
		// takes the resource from the vector and initiates a transfer request
    		for (int i = 0; i < results.size(); i++)
    		{
    			// vector contains ResourceObjects
    			ResourceObject tempresource = (ResourceObject) results.elementAt(i);
    			parent.MakeTransferRequest(tempresource.GetResourceName(), GetPluginID(), tempresource.GetID(), Integer.parseInt(tempresource.GetPluginID()), true, false);
			// as before provide filename, plugin id, source user id, source plugin id, visibility of dialog boxes, whether path is absolute
			
			// again we will send a message, this is identical as above
			// first create the hashmap that will store the message parts
			HashMap messageparts = new HashMap();
						
			Hashtable ua = parent.GetUser().GetAttributes();

			// create the message elements. These HAVE to be Strings
			messageparts.put("PLUGINID", String.valueOf(PluginID));		// We will provide the ID of the Plugin that is sending this message (this also represnts the target Plugins ID)
			messageparts.put("TYPE", "FILEREQUESTMESSAGE");  		// Simple way of determining the type of message	
			messageparts.put("SENDERID", (String) ua.get("UniqueID"));  	// Our Unique ID so the target knows who it is from
			messageparts.put("SENDERNICK", (String) ua.get("Nickname"));  	// Our Nickname so the target knows who is is from
			messageparts.put("MESSAGE", "Just getting a file off you!!");	// The message we are sending to the target
				
			// we now get the framework to send the message
			long messid = parent.SendMessage(tempresource.GetPipeAd(), 	     messageparts, 					this);
			//		    		  Pipe advert of target,   the hashmap containing the message,  what component is interested (not really used - so 'this' is fine)
	
			// again message sending is asynchronous
			JOptionPane.showMessageDialog(null, "ExamplePlugin: ID of Sent Message" + messid, "Sent Message ID", JOptionPane.WARNING_MESSAGE);						

    		}
	}
	
	// method to activate the plugin preferences
	public void ActivatePluginPreferences()
	{	
		// for this simple plugin, clicking on the icon will just make this frame become visible
    		this.setVisible(true);
    		
    	}	
	
	// method to change the status of this peer
	public void StatusChange(String status)
	{
		// for this simple plugin we will just popup a message saying that the status has changed
		JOptionPane.showMessageDialog(null, "ExamplePlugin: You have changed your status to " + status, "Status change", JOptionPane.WARNING_MESSAGE);						
		// a more complex plugin may want to react to the change
	}
	
	// method to inform the change of state of a peer on the contact list
	public void ChangeOfPeerStatus(String id, String status, String nick, Image icon)
	{
		// not relevant for this plugin
	}
	
	// method to kill a plugin
	// this method should tidy up the plugin so that it is ready to be shut down. This may involve saving settings, etc
	public void KillPlugin()
	{
		// this example plugin will not need to do any tidying up, due to its simplicity
	}
	
	// method to list the resources that this plugin will make available to the rest of the network
    	public Vector GetAvailableResources()
    	{
    		Vector resources = new Vector();
    	
    		// for this example, the plugin will only make available one resource (the Test.txt file)
    		// this needs to be represented as a ResourceTemplate and placed within a vector
    		// we use the method in the ClientFramework to create the ResourceTemplate
    		
		resources.add(parent.CreateResourceTemplate(PluginID, 		0, 	     5,       "Test.txt",     "Shared file"));
    						//  	    ID of plugin, Resource ID, MediaType ID, Resource Name, Resource Description
    		return resources;
    	}
    	
    	// method to specify the download location
    	public String IncomingLocation()
    	{
    		return parent.GetPluginsPath() + "ExamplePlugin/Received";
    	}
    	
    	// method to specify the upload location
    	public String OutgoingLocation()
    	{
    		return parent.GetPluginsPath() + "ExamplePlugin/Shared";
    	}
    	
    	// method to inform the plugin that a file transfer has succeeded
    	public void FileTransferSuccess(Boolean success, String filename, String source)
    	{
    		// we will popup a messagebox to show the success of any file transfer.
    		// depending on the nature of your plugin, you might not wish to make use of this method
    		JOptionPane.showMessageDialog(null, "ExamplePlugin: Transfered " + filename + "? " + success.toString(), "Transfer results", JOptionPane.WARNING_MESSAGE);						
    	}
    	
    	// called by the framework to return results of a resource search
    	// this example plugin does not perform any resource searhes
    	public void SearchResults(Vector results)
    	{ return; }
    	
    	// called by the framework to inform the plugin that the message of the given ID was successfully/unsuccessfully sent
    	public void SentMessage(long id, boolean status)
    	{
    		JOptionPane.showMessageDialog(null, "ExamplePlugin: Message ID:" + id + " Sent successfully:" + status , "Message Sent", JOptionPane.WARNING_MESSAGE);						
	}
    	
    	// ******************************************
    	// ***** End of PluginInteface methods ******
    	// ******************************************
    	
    	// constructor
	public ExamplePlugin(ClientFramework parent)
	{
		super("Example Plugin");
		this.parent = parent;
	
		// we will create a very simple frame for this example
		JLabel l = new JLabel("Plugin preferences would typically go here", SwingConstants.CENTER);
		
		Container contentPane = this.getContentPane();
        	contentPane.setLayout(new BorderLayout(5,5));
		contentPane.add("Center", l);

		// Deals with window closure requests
		this.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				setVisible(false);
			}
		});			
		
		this.setLocation(300,300);
		this.setIconImage((GetPluginIcon()).getScaledInstance(18, 18,Image.SCALE_DEFAULT));		

		this.setSize(350,300);
		this.setVisible(false);
	}
	
	// method called by client when this plugin received a message
	// the only message this plugin should receive is the FILEREQUESTMESSAGE that is sent when a file transfer is made
	public void MessageArrived(HashMap messageparts)
	{
		// first check to see if this message is supposed to come here
		// usually not needed, but better safe than sorry
		if ((new Integer((String)messageparts.get("PLUGINID"))).intValue() != PluginID)
			return;  
				
		// now check the type of message
		if (((String)(messageparts.get("TYPE"))).equals("FILEREQUESTMESSAGE"))
		{
			// display a dialog window
			JOptionPane.showMessageDialog(null, "ExamplePlugin\nMessage from " + (String) messageparts.get("SENDERNICK") + ": " + (String) messageparts.get("MESSAGE"), "Message", JOptionPane.WARNING_MESSAGE);						
		}
	}
}
