package org.nzdl.gsdl.GsdlCollageApplet;

import java.applet.Applet;
import java.awt.*;
import java.net.*;

/**
 * 
 *  @author Katrina Edgar
 *  @author David Bainbridge
 *
 * Main class for the GsdlCollageApplet<br>
 * Processes the parameters passed through the Applet<br>
 * Builds an appropriate starting url from these parameters<br>
 * Creates a storage class for downloaded images<br>
 * Starts thread to download images and their associated url<br>
 * Starts thread to display downloaded images on the applet screen<br>
 */
 
public class GsdlCollageApplet extends Applet {


    /** Amount of error checking output produced <br>
     *  Ranges from 0 - no output to 3 - maximum output */ 
    protected int verbosity_     = 0;
    /** Indicates whether java2 functionality should be used <br>
     *  If true will allow advanced image processing techniques to occur, 
     *  such as fading and colouring using pixel manipulation <br>
     *  If false, images will maintain an alpha value of 1 (appear solid), 
     *  newer images will simply be pasted on top of existing images <br> */
    protected boolean isJava2_  = true;
    /** Number of nested links to follow When used with greenstone,
     *  controls to which level of the document links will be followed For
     *  example a maximum depth of 1 will mean only the top page of a
     *  document will be examined, while a depth of 2 will include sections
     *  within this document, 3 includes sections within sections, and so
     *  on */
    protected int maxDepth_     = 3;

    /** Maximum number of images to display on the canvas */
    protected int maxDisplay_ = 25;

    /** Maximum number of downloaded images to store <br> Prevents applet
     *  from using excessive amounts of bandwidth by downloading too many
     *  images simulataneously*/
    protected int maxDownloads_ = Integer.MAX_VALUE;

    /** Types of images permitted in the collage, for example gif, jpg,
     * png... */
    protected String imageType_ = ".jpg%.png";

    /** Caption of the collage */
    protected String caption_ = "";

    /** Background color of applet screen */
    protected Color bgcolor_ = new Color(150, 193, 155);

    /** Time lapse between repainting of the applet */
    protected int refreshDelay_ = 2000;
    
    /** Stores an image and url pair and provides associated methods */
    protected DownloadImages download_images_ = null;
    /** Downloads images from a starting url, recursively follows nested
     * links */
    protected DownloadUrls download_thread_   = null;
    /** Image processing and placement on applet screen */
    protected DisplayImages display_thread_   = null;

   

    /** Gets verbosity */
    public int verbosity()    { return verbosity_; }
    /** Gets maximum depth for nested links */
    public int maxDepth()     { return maxDepth_; }

    /** Gets maximum number of images to display */
    public int maxDisplay() { return maxDisplay_;}

    /** Gets maximum number of images to store during downloading */
    public int maxDownloads() { return maxDownloads_; }
    /** Gets the refresh delay used between repaint */
    public int refreshDelay() { return refreshDelay_; }

    /** Gets parameters from the applet code and stores locally.
     * Forms a starting url for image retrieval to begin from.
     * The starting url is formed either by:
     *  * Using the image_url parameter as provided, which is assumed to 
     *     be a complete url
     *  * If this parameter does not exist, the assumption is that the 
     *     collage is being incorporated with the Greenstone Digital Library 
     *     Software. The starting url is formed by concatenating
     *     the gwcgi, collection and classifier parameters as provided.
     * Then starts downloading and displaying images */

    Thread paint ;

    public void init() 
    {	    
	if (verbosity_ >= 4) { 
	    System.err.println("Attempting to retrieve parameters...");
	}

	// gets the parameters specified
	String verbosity_param      = getParameter("verbosity");
	String is_java2_param       = getParameter("isJava2");
	String max_depth_param      = getParameter("maxDepth");
	String max_downloads_param  = getParameter("maxDownloads");
	String max_display_param    = getParameter("maxDisplay");
	String refresh_delay_param  = getParameter("refreshDelay");
	String image_type_param     = getParameter("imageType");
	String bgcolor_param        = getParameter("bgcolor");
	String caption_param        = getParameter("caption");
        String document_root        = getParameter("documentroot");
        String gwcgi                = getParameter("gwcgi");        


	// Check it isn't null
	if ((verbosity_param!=null) && (!verbosity_param.startsWith("_"))) {
	    verbosity_  = Integer.parseInt(verbosity_param);
	}
	else {
	    verbosity_ = 1;
	}


	if (verbosity_ >= 4) { 
	    System.err.println("Got parameters.");
	}

	if (caption_param != null && !caption_param.startsWith("_")) {
	    caption_ = caption_param;
	}
	else {
	    if (verbosity_ >= 4) { 
		System.err.println("No Caption: setting to a space.");
	    }
	    caption_ = " ";
	}

	if ((bgcolor_param != null) && (!bgcolor_param.startsWith("_"))) {
	    if (bgcolor_param.startsWith("#")) {
		bgcolor_ = Color.decode(bgcolor_param);   
	    }
	    else {
		String [] c = bgcolor_param.split(",");
		if (c.length == 3)
		    bgcolor_ = new Color(Integer.parseInt(c[0]), Integer.parseInt(c[1]), Integer.parseInt(c[2]));
	    }
	    if (verbosity_ >= 4){ 
		System.err.println("Set BG to be " + bgcolor_.toString());
	    }
	}
	else {
	    if (verbosity_ >= 4) { 
		System.err.println("No BG: setting to NZDL green.");
	    }	   
	    bgcolor_ = new Color(150, 193, 155);
	}

	if ((image_type_param != null) && (!image_type_param.startsWith("_"))) {
	    imageType_ = image_type_param;
	}

	if ((is_java2_param == null) || (is_java2_param.equals("auto")) || (is_java2_param.startsWith("_"))) {
	    String version = System.getProperty("java.version");
	    version = version.substring(0, version.lastIndexOf("."));
	    System.err.println("VERSION: " + version);
	    float ver = (new Float(version)).floatValue();
	    isJava2_ = (ver >= 1.2) ? true : false;
	}
	else {
	    isJava2_ = (is_java2_param.equals("true")) ? true : false;
	}

	if ((max_depth_param != null) && (!max_depth_param.startsWith("_"))) {
	    // System.err.println("maxDepth = " + max_depth_param);
	    maxDepth_ = Integer.parseInt(max_depth_param);
	}

	if ((max_downloads_param!=null) && (!max_downloads_param.startsWith("_"))) {
	    maxDownloads_ = Integer.parseInt(max_downloads_param);
            System.out.println(" maxDownloads " + maxDownloads_ );
	    maxDownloads_=50;
	}

	if ((max_display_param!=null) && (!max_display_param.startsWith("_"))) {
	    maxDisplay_ = Integer.parseInt(max_display_param);
              
	}

	if ((refresh_delay_param!=null) && (!refresh_delay_param.startsWith("_"))) {
	    refreshDelay_ = Integer.parseInt(refresh_delay_param);
	}

       
        if (document_root !=null){          
	    document_root = document_root.substring(1);
            if (document_root.indexOf("/") > 0 ){
		document_root = document_root.substring(0, document_root.indexOf("/"));
	    }
	    else{
		document_root = gwcgi; 	
	    }
	}


	String image_url  = getParameter("imageURL"); 
	String image_ignore  = getParameter("imageIgnorePrefix"); 
	String href_musthave  = getParameter("hrefMustHave"); 
	String image_mustnothave = getParameter("imageMustNotHave");

	// builds starting url when incorporated with Greenstone
	if (image_url==null)
	{
	    String gwcgi_param  = getParameter("gwcgi");
	    gwcgi_param = tidy_URL(gwcgi_param, true);
	
	    String collection_param  = getParameter("collection");
	    String classifier_param  = getParameter("classifier");

	    image_url = gwcgi_param + "a=d";
	    image_url += "&c=" + collection_param;
	    image_url += "&cl=" + classifier_param;
	}

	MediaTracker trk = new  MediaTracker(this);

	// creates a class to store the image and it's associated url
	download_images_ = new DownloadImages( this, verbosity_,isJava2_ );
	// starts the download image thread with the starting url

        download_thread_ = new DownloadUrls(this, download_images_, 
					    image_url, href_musthave, image_mustnothave, 
					    image_ignore, imageType_,document_root,verbosity_,trk);
	// starts the display image thread with the currently downloaded images
	display_thread_ = new DisplayImages(this, download_images_,isJava2_, bgcolor_);
	
    }

 
    /** Goes to the url associated with the image that is clicked on screen<br>
     *  Displays the url containing the image in a new window */
    public boolean mouseDown(Event event, int x, int y)
    {
	// determines which image was clicked on
	CollageImage cimage = display_thread_.clickedOnImage(x,y);
	// if they were clicking on an image (as opposed to background)
	if (cimage != null)
	{
	    System.err.println("Click on image: from url = " + cimage.from_url_);
	    try {
		// displays the associated url in a new window
                URL from_url = null;		
		
		java.util.regex.Pattern p = java.util.regex.Pattern.compile("cl=CL\\d(\\.\\d)*\\s");
		java.util.regex.Matcher m = p.matcher(cimage.from_url_.trim()+" ");

                if (m.find() ){
		    from_url = cimage.url_;
		}
		else{
		    from_url =  new URL(cimage.from_url_  + "#" + cimage.name_);
		}
		getAppletContext().showDocument(from_url,"gsdlDoc");
	    } 
	    catch (MalformedURLException e) { 
		e.printStackTrace();
	    }

	}
        return true;
    }
    
    /** Start threads for downloading and displaying images */
    public void start() 
    {
	
	download_thread_.start();	

	display_thread_.start();

         paint =  new Thread(new Runnable(){
                public void run() {
		    try {

			Thread curr_thread = Thread.currentThread();
	    
			while (curr_thread == paint) {
	      
			   repaint();
			    
			    Thread.sleep(2000);
			    curr_thread = Thread.currentThread();
			}

	    
		    } catch (Exception e) {
			
		    }
		}


	    });

	    paint.start();
   
    }

    /** Stops threads for downloading and displaying images */
    public void stop() 
    {
	download_thread_.stop();
	display_thread_.stop();
	
	download_thread_ = null;
	display_thread_ = null;
	
    }

    /** Destroys threads for downloading and displaying images */
    public void destroyed() 
    {
	download_thread_ = null;
	
	display_thread_ = null;
	
    }


    /** Repaints the applet */
    public void update(Graphics g) 
    { 
	// System.err.println("Update called");
	paint(g); 
    } 
    
    /** Repaints the applet using the paint method of the thread that is
     * currently displaying images */
    public void paint(Graphics g) {
	if (display_thread_!=null)
	    {	
	      
	    	//display_thread_.display_collage();
	    	  display_thread_.paint(g);
	    }
	else
	    {
		System.err.println("Applet still trying to paint!!");
	    }

	
	
    }

  
    
    /** Ensures a URL address (as string) has a protocol, host, and file.
     *
     * If the URL is a CGI script URL, it should be tidied up so that it is
     * appropriate to tage attrib=value pairs on the end.  This means it
     * must either end with a "?" or (if it contains a question-mark
     * internally) end with a "&". */
    String tidy_URL(String address, boolean isCGI) {

	// System.err.println("tidy URL: " + address);
	
	// make sure the URL has protocol, host, and file
	if (address.startsWith("http")) {
	    // the address has all the necessary components
	} else if (address.startsWith("/")) {
	    // there is not protocol and host
	    URL document = getDocumentBase();
	    String port = "";
	    if (document.getPort()!=-1) {
		port = ":" + document.getPort();
	    }
	    address = "http://" + document.getHost() + port  + address;
	} else {
	    // this URL is relative to the directory the document is in
	    URL document = getDocumentBase();
	    String directory = document.getFile();
	    int end = directory.lastIndexOf('/');
	    String port = "";
	    if (document.getPort()!=-1) {
		port = ":" + document.getPort();
	    }
	    directory = directory.substring(0,end + 1);
	    address = "http://" + document.getHost() + port + directory + address;

	}

	// if the URL is a cgi script, make sure it has a "?" in ti,
	// and that it ends with a "?" or "&"
	if (isCGI) {
	    if (address.indexOf((int) '?') == -1) { 
		address = address + "?";
	    } else if (!address.endsWith("?")) {
		address = address + "&";
	    }
	}

	return address;
    }


}
