package org.greenstone.applet.GsdlCollageApplet;

public class MyAffineTransform {

    public double scaleX = 0;
    public double scaleY = 0;
    public double translateX = 0;
    public double translateY = 0;
    public boolean overlap = false;

    public MyAffineTransform (int image_x_dim, int image_y_dim) {

	random_set_pos(image_x_dim, image_y_dim);
    }

    /** The amount to adjust the size of an image so that it fits into the applet screen
     *  @param image_x_dim the width of the image to scale
     *  @param image_y_dim the height of the image to scale
     *  @return a value by which to scale the image to ensure it will fit in the applet */
    private double scaleFactor (int image_x_dim, int image_y_dim) {

	double scale_factor = 1.0;

	//to avoid attempting to divide by 0
	// TODO: Why is it even 0? I had initialised app_x/y_dim_ with fallback to ensure non-0
	// Hard to debug, as I've seen it happen only once.
	//if(DisplayImages.app_x_dim_ == 0 || DisplayImages.app_y_dim_ == 0) {
	//    return scale_factor;
	//}

	// three quarters of the application width & height
	int tol_app_x_dim = 3*DisplayImages.app_x_dim_/4;
	int tol_app_y_dim = 3*DisplayImages.app_y_dim_/4;

	// if the image is too big, calculate a fraction
	// by which to reduce the image
	if (image_x_dim>tol_app_x_dim)
	{
	    scale_factor = image_x_dim/tol_app_x_dim + 1;
	}

	if (image_y_dim>tol_app_y_dim)
	{
	    int y_scale_factor = image_y_dim/tol_app_y_dim + 1;
	    // take the biggest of the two as the same fraction must
	    // be applied to both the x and y values to keep the image
	    // in proportion
	    if (y_scale_factor>scale_factor)
	    {
		scale_factor = y_scale_factor;
	    }
	}

	return scale_factor;
    }

    /** Determines the placement of new images on the applet screen <br>
     *  First the image is scaled, then the function loops until a satisfactory
     *  image position is found. This is done by randomly selecting an x and y
     *  co-ordinate for the image, then determining how much whitespace will be
     *  covered if the image were to be placed at this position in the collage.
     *  The standards for loop termination are as follows:<br>
     *  1. On any occasion a whitespace coverage of greater than 70% will result 
     *  in the loop being terminated.<br>
     *  2. After three times through the loop, a whitespace coverage of 50% will
     *  also allow the loop to terminate (a less stringent condition). <br>
     *  3. After seven times through, the loop will terminate and the best
     *  position will be used by default.<br>
     *  This function also updates the used space array after image position has been selected.
     *  
     *  @param image_x_dim the width of the image
     *  @param image_y_dim the height of the image
     *  @return a transform operation by which to move the image from the origin */
    protected void random_set_pos(int image_x_dim, int image_y_dim) 
    {

	double scale_factor = scaleFactor(image_x_dim, image_y_dim);

	// scale the image (will be 1 and therefore no change as a default)
	image_x_dim/=scale_factor;
	image_y_dim/=scale_factor;
	
	// initialise variables required to determine image placement
	int image_x_pos = 0;
	int image_y_pos = 0;
	int best_x = 0;
	int best_y = 0;
	double best_clear = 0;
	double clear = 100;
	int stoploop = 0;
	
	do {
	    // increment the loop counter
	    stoploop++;

	    // the number of positions that the image could occupy on the x axis
	    int safe_x_dim = DisplayImages.app_x_dim_ - image_x_dim;
	    double rx = Math.random();
	    // randomly pick an x co-ordinate for the image
	    image_x_pos= ((int)(rx*safe_x_dim));
	    
	    // same process as for the x co-ordinate
	    // ensuring the y co-ordinate will fit on the screen
	    int safe_y_dim = DisplayImages.app_y_dim_ - image_y_dim;
	    double ry = Math.random();
	    // randomly pick a y co-ordinate for the image
	    image_y_pos= ((int)(ry*safe_y_dim));
	    
	    double whitespace = 0;
	    double space = 0;
	    
	    // determine how much whitespace the image will cover if placed in the
	    // current position and how much overlap will occur
	    for (int n = image_x_pos; n < (image_x_pos + image_x_dim); n++) {
		for (int m = image_y_pos; m < (image_y_pos + image_y_dim); m++) {
		    if (DisplayImages.used_space[n][m] == 0)
			whitespace++;
		    space++;
		}
	    }
	    
	    // divide the amount of whitespace covered by the amount of overlap
	    clear = whitespace/space;
	    // if this value is better than previous calculations, save these co-ordinates
	    if (clear > best_clear) {
		best_x = image_x_pos;
		best_y = image_y_pos;
		best_clear = clear;
	    }

	    if ((image_x_dim > (DisplayImages.app_x_dim_ / 2)) || (image_y_dim > (DisplayImages.app_y_dim_ / 2)))
		break;

	} while ((clear < 0.70 || (stoploop > 3 && clear < 0.50)) && stoploop < 7);
	    
	// if we only terminated because we went through so many times,
	// then we set the position to the best value possible
	if (stoploop == 7) {
	    image_x_pos = best_x;
	    image_y_pos = best_y;
	}

	// indicate that the space where the image is to be placed is now used
	for (int n = image_x_pos; n < (image_x_pos + image_x_dim); n++)
	    for (int m = image_y_pos; m < (image_y_pos + image_y_dim); m++) {
		DisplayImages.used_space[n][m]++;
		if (DisplayImages.used_space[n][m] > DisplayImages.NO_IMAGES_OF_OVERLAP)
		    overlap = true;
	    }
	
	translateX = image_x_pos;
	translateY = image_y_pos;
	
	// scale the image appropriately
	scaleX = 1.0/scale_factor;
	scaleY = 1.0/scale_factor;
	
	return;
    }

}
