package org.greenstone.gatherer.feedback;

import java.awt.image.*;
import java.awt.geom.*;
import java.awt.geom.Line2D.*;
import java.awt.geom.Line2D.Double;
import java.io.*;
import javax.swing.*;
import java.awt.*;

/**
 * This is the class that will allow user to draw a same line to 2 different BufferedImage
 * at the same time.
 * The first BufferedImage is BufferedImage with some Image as the based and then
 * we draw a line on it, and the second BufferedImage is just a transparent Image and then we 
 * draw a line on it. The line drawn in first BufferedImage is exactly the same with the line
 * drawn in second BufferedImage.The Image drawn in the first bufferedimage is the
 * screen shot image of the whole screen.
 * @author Veronica Liesaputra
 */
public class Graphs
{ 
    /**
     * This is the first buffered image.
     * It will drawn with an image first to be its based, and a line  
     * that are identical to line drawn the second BufferedImage, will be drawn on it.
     */
    private BufferedImage I = null;

    /**
     * This is the second buffered image.
     * Its a transaparent buffered image and a line that are indetical to line
     * drawn in the first BufferedImage, will be drawn on it. 
     */
    private BufferedImage I2;

    /**
     * This is the Graphics for the first BufferedImage.
     * This will allow user to draw a line and an image on the first buffered image.
     */
    private Graphics2D G;
    
    /**
     * This is the Graphics for the second BufferedImage.
     * This will allow user to draw a line on the second buffered image.
     */
    private Graphics2D G2;

    /**
     * This is the arrays of the 3 BufferedImage.
     */
    private BufferedImage[] screen;

    /**
     * This is the graphics for screen[0] BufferedImage.
     * This will allow user to draw something on the screen[0] image.
     */
    private Graphics2D G3;
  
    /**
     * This is the width of the image.
     */
    private double imwidth;

    /**
     * This is the height of the image.
     */
    private double imheight;

    /**
     * This is the constructor that will initialised the BufferedImage and
     * its Graphics.
     * (Precondition: (sh != null))
     * @param sh is the images.
     */
    public Graphs (BufferedImage[] sh)
    {
	screen = sh;

	if (screen[0] != null)
	    { 
		imwidth = screen[0].getWidth();
		imheight = screen[0].getHeight();


		if((screen[1] == null)&& (screen[2] == null))
		    {
			I = new BufferedImage(screen[0].getWidth(),screen[0].getHeight(),
					      BufferedImage.TYPE_INT_RGB);
			I2 = new BufferedImage(I.getWidth(),I.getHeight(),
					       BufferedImage.TYPE_INT_ARGB);
		    }
		else
		    {
			I = screen[1];
			I2 = screen[2];
		    }
		start();
	    }
	else
	    System.out.println("weird");
    }

    /**
     * This method will make sure that everything is null-ed and dispose properly.
     */
    public void flush()
    {
	G.dispose();
	G = null;
	G3.dispose();
	G3 = null;
	G2.dispose();
	G2 = null;

	int i;
	for ( i = 0 ; i < 3; i++)
	    {
		if (screen[i] != null)
		    {
			screen[i].flush();
			screen[i] = null;
		    }
	    }

	I.flush();
	I = null;
	I2.flush();
	I2 = null;
	System.gc();
    }

    /**
     * This method will cleared the scribble lines in the images.
     */
    public void reset()
    {
	I.flush();
	I = null;
	System.gc();
	I2.flush();
	I2 = null;
	G.dispose();
	System.gc();
	G2.dispose();
	G = null;
	G2 = null;
	System.gc();

	I = new BufferedImage(screen[0].getWidth(),
			      screen[0].getHeight(),
			      BufferedImage.TYPE_INT_RGB);
	I2 = new BufferedImage(I.getWidth(),I.getHeight(),
			       BufferedImage.TYPE_INT_ARGB);

	screen[1] = null;
	screen[2] = null;

	start();
    }
    /**
     * This method will setup the 3 Graphics for the 3 BufferedImage.
     * Here the graphics for the bufferedimage will be created and the appropriate image
     * will be drawn to the first bufferedimage.  
     */
    public void start ()
    {
	G3 = screen[0].createGraphics();
	G3.drawImage((Image) screen[0],0,0,new JLabel());

	G = I.createGraphics();
	if (screen[1] == null)
	    G.drawImage((Image) screen[0],0,0,new JLabel());
	else
	    G.drawImage ((Image) screen[1],0,0,new JLabel());
	G2 = I2.createGraphics();
    }
 
    /**
     * This method will draw a red line on both BufferedImage from the source point
     * to the destination point.
     * @param x1 is the x-coordinate of the source point.
     * @param y1 is the y-coordinate of the source point.
     * @param x2 is the x-coordinate of the destination point.
     * @param y2 is the y-coordinate of the destination point. 
     */
    public void drawLines(int x1,int y1,int x2,int y2)
    {
	G2.setColor(Color.red);
	G.setColor(Color.red);

	G.setStroke(new BasicStroke(2.5f));
	G2.setStroke(new BasicStroke(2.5f));

	G2.drawLine(x1,y1,x2,y2);
	G.drawLine(x1,y1,x2,y2);
    }

    
    /**
     * This method will draw a white line on all 3 BufferedImage from the source point
     * to the destination point.
     * @param x1 is the x-coordinate of the source point.
     * @param y1 is the y-coordinate of the source point.
     * @param x2 is the x-coordinate of the destination point.
     * @param y2 is the y-coordinate of the destination point. 
     */
    public void eraseLines(int x1,int y1,int x2,int y2)
    {
	G3.setColor(Color.white);
	G2.setColor(Color.white);
	G.setColor(Color.white);

	G.setStroke(new BasicStroke(25.5f));
	G2.setStroke(new BasicStroke(25.5f));
	G3.setStroke(new BasicStroke(25.5f));
	
	G3.drawLine(x1,y1,x2,y2);
	G2.drawLine(x1,y1,x2,y2);
	G.drawLine(x1,y1,x2,y2);
    }

    /**
     * This method will get the first BufferedImage.
     * This is the BufferedImage where it will already be drawn with the
     * screen shot image and the lines.
     * @return the first BufferedImage.
     */
    public BufferedImage getImage ()
    {
	return I;
    }

    /**
     * This method will get the second BufferedImage.
     * This is the BufferedImage where its base is transparent and it will
     * already be drawn with the lines.
     * @return the second BufferedImage.
     */
    public BufferedImage getImage2()
    {
	return I2;
    }

    /**
     * This method will get the image without scribble lines only the white lines.
     * @return the image without scribble lines.
     */
    public BufferedImage getScreenImage()
    {
	return screen[0];
    }

    /**
     * This method will get the window out of the whole screen image.
     * @param xcoord the xcoordinate of the window in the image.
     * @param ycoord the ycoordinate of the window in the image.
     * @param width  the width of the window in the image.
     * @param height the height of the window in the image.
     * @return the BufferedImage of the window only from the 3 buffered image.
     */
    public BufferedImage[] getWindowVersion(int xcoord,int ycoord,int width,int height)
    {
	BufferedImage[] window;
	window = new BufferedImage[3];

	Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
	
	if (xcoord < 0 ) 
	    xcoord = 0;
	if (ycoord < 0)
	    ycoord = 0;

	if (xcoord >= imwidth)
	    xcoord = (int)(imwidth - 1);
	if (ycoord >= imheight)
	    ycoord = (int)(imheight - 1);
	if ((xcoord + width) > imwidth)
	    width = (int)(imwidth - xcoord);
	if ((ycoord + height) > imheight)
	    height = (int)(imheight - ycoord);

	if (width <= 0)
	    width = 1;
	if (height <= 0)
	    height = 1;

	window[0] = getClipVersion(screen[0],xcoord,ycoord,width,height);
	
	window[1] = getClipVersion(I,xcoord,ycoord,width,height);
	
	window[2] = getClipVersion(I2,xcoord,ycoord,width,height);
	
	return window;
    }
    
    /**
     * This method will return the subimage of the big buffered image.
     * @param tag the original buffered image.
     * @param x   the x location of subimage.
     * @param y   the y location of subimage.
     * @param w   the width of the subimage.
     * @param h   the height of the subimage.
     * @return    the subimage.
     */
    public BufferedImage getClipVersion (BufferedImage tag,int x, int y, int w, int h) 
    {
	BufferedImage sub;
	sub = tag.getSubimage(x,y,w,h);
	
	return sub;
    }

    /**
     * This method will return the screen image version of the give buffered image.
     * @param sh the buffered image that we going to draw in the screen image version.
     * @param xcoord   the x location of subimage.
     * @param ycoord   the y location of subimage.
     * @param w   the width of the subimage.
     * @param h   the height of the subimage.
     */
    public void setScreenVersion(BufferedImage[] sh,int xcoord,int ycoord,int w, int h)
    {
	if (xcoord < 0 ) 
	    xcoord = 0;
	if (ycoord < 0)
	    ycoord = 0;

	if (xcoord >= imwidth)
	    xcoord = (int) (imwidth - 1);
	if (ycoord >= imheight)
	    ycoord = (int) (imheight - 1);
	if ((xcoord + w) > imwidth)
	    w = (int) (imwidth - xcoord);
	if ((ycoord + h) > imheight)
	    h = (int) (imheight - ycoord);

	if (w <= 0)
	    w = 1;
	if (h <= 0)
	    h = 1;
       
	G3.drawImage(sh[0], xcoord,ycoord,new JLabel());

        
        G.drawImage(sh[1], xcoord,ycoord,new JLabel());
	
	
	G2.drawImage(sh[2], xcoord,ycoord,new JLabel());
    }
}
    








