package org.greenstone.gatherer.feedback;

import java.awt.image.*;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.*;
import java.awt.geom.*;
import java.awt.geom.Line2D.*;
import java.awt.geom.Line2D.Double;
import java.awt.event.*;
import java.awt.event.MouseEvent;
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import javax.swing.border.*;
import javax.swing.BorderFactory;

import org.greenstone.gatherer.util.JarTools;

/**
 * This class allows user to make scribble lines in the image.
 * This class will display an image to a label and if the user drag inside the label
 * then it will draw coloured line as the user drag the mouse.
 * Image here is the screen shot of the whole screen size.
 * @author Veronica Liesaputra
 */
public class SelectPicture extends WindowAdapter
{
    /**
     * This is the images that stored all the images for the whole screen size image.
     */
    private BufferedImage[] screen;
  
    /**
     * This is the images that stored all the images for the window image.
     */
    private BufferedImage[] window;

    /**
     * This is the buffered image that contains the line that are drawn all
     * over the screen image.
     */
    private BufferedImage bi;
    
    /**
     * This is the buffered image of the line that are drawn all over the screen image.
     */
    private BufferedImage bi2;

    /**
     * This is the buffered image of the screen image.
     */
    private BufferedImage bi3;

    /**
     * This is the buffered image that contains the line that are drawn all over the window image.
     */
    private BufferedImage bi4;

    /**
     * This is the buffered image of the line that are drawn all over the window image.
     */
    private BufferedImage bi5;

    /**
     * This is the buffered image of the window image.
     */
    private BufferedImage bi6;

    /**
     * This is the window's x-coord in the screen image.
     */
    private int xcoord;

    /**
     * This is the window's y-coord in the screen image.
     */
    private int ycoord;

    /**
     * This is the window's width in the screen image.
     */
    private int width;

    /**
     * This is the window's height in the screen image.
     */
    private int height;
    
    /**
     * This is to block all the input in this window while waiting.
     */
    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
    
    /**
     * This variable will hold the resource of the words that is stored in Messages.properties file.
     * The calling using messages.getString(someString) will caused someString to be translated
     * into some other string that is hold in that file.usually it will caused it to be translated
     * to the language that the user use or choose to have as stated in Locale.
     */
    private static ResourceBundle messages;
    
    /**
     * This variable hold the comments that user entered when they are drawing lines into the image.
     */
    private String details;
    
    /**
     * This variable is a flag to say whether or not user wants to send the feedback straight away.
     */
    private boolean sendNow;

    /**
     * This variable is a flag to say whether the user wants to draw the scribble lines or
     * to erase the image.
     */
    private boolean drawNow;

    /**
     * This variable is a flag to say whether or not the image user wants to send is window
     * or the whole screen image.
     */
    private boolean windowNow;

    /**
     * This method will make a modal-dialog that will allow user to draw a line all over the image.
     * @param sh the buffered images of the screen image.
     * @param wh the buffered images of the window image.
     * @param iswindow the flag to say whether user wants to send window or whole screen image.
     * @param screen_details the comments that user typed for this screenshot.
     * @param msg hold the resource of the words that is stored in Messages.properties file.
     */
    public SelectPicture(BufferedImage[] sh,BufferedImage[] wh,boolean iswindow,String screen_details,ResourceBundle msg)
    {
	windowNow = iswindow;
	drawNow = true;
	details = screen_details;
	messages = msg;
	window = wh;
	screen = sh;
    }
    
    /**
     * This method setting up the window's bounds inside the screen image.
     * @param x the window's x-coordinate in the screen image.
     * @param y the window's y-coordniate in the screen image.
     * @param w the window's width in the screen image.
     * @param h the window's height in the screen image.
     */
    public void setWindowBounds (int x,int y,int w,int h)
    {
	xcoord = x;
	ycoord = y;
	width = w;
	height = h;
	makeNewWindow();
    }

    /**
     * This method will get which one user wants to send the window or screen image.
     * @return the flag whether user wants to send window or screen image. 
     */
    public boolean getIsWindow()
    {
	return windowNow;
    }

    /**
     * This method will get the screen image of the screenshot with the line drawn all over it.
     * @return  this is the screen image with the line drawn all over it.
     */
    public BufferedImage getImage()
    {
	return bi;
    }

    /**
     * This method will get the screen image of the screenshot.
     * @return  this is the screen image.
     */
    public BufferedImage getImage3()
    {
	return bi5;
    }

    /**
     * This method will get the screen image of only the line that drawn all over the image of
     * the screenshot.
     * @return  this is the screen image of only the line.
     */
    public BufferedImage getImage2()
    {
	return bi2;
    }

    /**
     * This method will get the window image of the screenshot with the line drawn all over it.
     * @return  this is the image with the line drawn all over it.
     */
    public BufferedImage getWindowImage()
    {
	return bi3;
    }

    /**
     * This method will get the window image of the screenshot.
     * @return  this is the window image.
     */
    public BufferedImage getWindowImage3()
    {
	return bi6;
    }

    /**
     * This method will get the window image of only the line that drawn all over the image of
     * the screenshot.
     * @return  this is the window image of only the line.
     */
    public BufferedImage getWindowImage2()
    {
	return bi4;
    }

    /**
     * This method will give the comments user made when they are drawing line over the picture.
     * @return this is the comment user made.
     */
    public String getDetails ()
    {
	return details;
    }

    public boolean getSendNow()
    {
	return sendNow;
    }

    /**
     * This method will make a modal-dialog that will have the image of the screen shot in the label,
     * allow user to draw a line all over the image and comments it as well. 
     */
    public void makeNewWindow()
    {
	JDialog f;
	f = new Selecting(this);
	f.setLocation(0,0);
    }

    /**
     * This class will make a modal-dialog that will have the image of the screen shot in the label,
     * allow user to draw a line all over the image and comments it as well. 
     */
    class Selecting extends JDialog implements ActionListener
    {
	/**
	 * This is the modal-dialog.
	 */
	private JDialog frame;
	
	/**
	 * This is the special label that allows user to draw a line all over the icon set in the label.
	 */
	private SelectionArea area;
	
	/**
	 * This is the text area where user can enter the comments they want to add.
	 */
	private JTextArea problem_details;
	
	/**
	 * This is the owner of this modal-dialog.
	 */
	private SelectPicture framework = null;
	
	/**
	 * This is the graphs that will allow to draw the line all over the screen image in the label and getting
	 * the image of it.
	 */
	private Graphs gp;

	/**
	 * This is the graphs that will allow to draw the line all over the window image in the label and getting
	 * the image of it.
	 */
	private Graphs gp2;

	/**
	 * This constructor will make  a modal-dialog that will have the image of the screen shot in the label,
	 * allow user to draw a line all over the image and comments it as well. 
	 * @param controller this is the owner of the modal-dialog.
	 */
	public Selecting(SelectPicture controller)
	{
	    Container contentPane;
   
	    contentPane = getContentPane();

	    gp = new Graphs(screen);
	    
	    window = gp.getWindowVersion(xcoord,ycoord,width,height);
	  
	    gp2 = new Graphs(window);

	    buildUI(contentPane);
	
	    framework = controller;
	   
	    setTitle(messages.getString("Showwhereistheproblem"));
	    setDefaultLookAndFeelDecorated(true);
	    setModal(true);

	    frame = this;
	    addWindowListener(framework);
	    setBackground(new Color(176,208,176)); 
	    
	    setLocation(0,0);
	  
	    pack();
	    setVisible(true);
	}

	/**
	 * This method will setup the contentpane of the modal-dialog.It will set the cursor for
	 * the label to be from the file pen.gif and set the image icon for the label.
	 * @param content this is the contentPane of the modal-dialog.
	 */
	private void buildUI(Container content) 
	{
	    final JPanel container;
	    container = new JPanel();
	    container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
	    container.setBackground(new Color(176,208,176));
	    container.setBorder(new EmptyBorder(5,5,5,5));

	   
	    ImageIcon image = createImageIcon(windowNow);
	    area = new SelectionArea(image, this);
	    area.setBackground(new Color(224,240,224));
	    area.setBorder(BorderFactory.createCompoundBorder
			   (BorderFactory.createLineBorder(Color.blue,4),
			    new EmptyBorder(10,10,10,10)));
	   
	    ImageIcon imgicon,imgicon2;
	    Image img,img2;
	    imgicon = JarTools.getImage("pen.gif");
	    img = imgicon.getImage();
	    img = img.getScaledInstance(24,24,Image.SCALE_SMOOTH);
	    imgicon2 = JarTools.getImage("eraserpen.gif");
	    img2 = imgicon2.getImage();
	    final Cursor cursor;
	    final Cursor cursor2;
	    cursor = Toolkit.getDefaultToolkit().createCustomCursor(img,new Point(0,0),"crayon");
	    cursor2 = Toolkit.getDefaultToolkit().createCustomCursor(img2,new Point(0,0),"eraser");
	    
	    area.setCursor(cursor);

	    Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
	    final JPanel iconarea = new JPanel();
	    iconarea.setBackground(new Color(176,208,176));
	    iconarea.add(area);
	    container.add(iconarea);
	    
	    String screen_label;
	    screen_label = " " + messages.getString("ScreenShotLabel");
	    JLabel label;
	    label = new JLabel(screen_label);
	    label.setBackground(new Color(176,208,176));
	    container.add(label);

	    JPanel panes;
	    panes = new JPanel();
	    panes.setLayout(new GridLayout(0,2));
	    panes.setBackground(new Color(176,208,176));

	    problem_details = new JTextArea(details);
	    problem_details.setWrapStyleWord(true);
	    problem_details.setEditable(true);
	    problem_details.setBackground(new Color(224,240,224));
	    JScrollPane scroll;
	    scroll = new JScrollPane(problem_details);
	    scroll.setBackground(new Color(176,208,176));
	    scroll.setPreferredSize(new Dimension(50,100));
	    scroll.setBorder(BorderFactory.createTitledBorder(
							      new EmptyBorder(0,0,0,0),
							      "Screen shot " + 
							      messages.getString("ProblemDetails")));

	    panes.add(scroll);

	    JPanel pane;
	    pane = new JPanel();
	    pane.setLayout(new GridLayout(2,3));
	    pane.setBackground(new Color(176,208,176));
	    pane.setBorder(new EmptyBorder(15,15,15,15));

	    if ((window == null) || (screen == null)) {System.out.println("How come!");}
	    else
		{
		    final JButton toggle;
		    
		    if (windowNow == false)
			{
			    toggle = new JButton("GLI window."); 
			    toggle.setToolTipText("Showing only GLI window.");
			}
		    else
			{
			    toggle = new JButton("Whole screen.");
			    toggle.setToolTipText("Showing whole screen.");
			}
		    toggle.setActionCommand("Toggle");
		    toggle.addActionListener(new ActionListener ()
			{
			    public void actionPerformed (ActionEvent e)
			    {
				frame.addMouseListener(mouse_blocker_listener);
				frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
				if (windowNow == true)
				    {
					windowNow = false;
					toggle.setText("GLI window.");
					toggle.setToolTipText("Showing only GLI window.");
					window[0] = gp2.getScreenImage();
					window[1] = gp2.getImage();
					window[2] = gp2.getImage2();
					gp.setScreenVersion(window,xcoord,ycoord,width,height);
					area.setIcon(new ImageIcon(gp.getImage()));
				    }
				else
				    {
					windowNow = true;
					toggle.setText("Whole screen.");
					toggle.setToolTipText("Showing whole screen.");
					
					window[0].flush();
					window[0] = null;
					window[1].flush();
					window[1] = null;
					window[2].flush();
					window[2] = null;
					window = null;
					BufferedImage tmp;
					gp2.getImage().flush();
					tmp = gp2.getImage();
					tmp.flush();
					tmp = null;
					gp2.getImage2().flush();
					tmp = gp2.getImage2();
					tmp.flush();
					tmp = null;
					gp2.flush();
					gp2 = null;
					System.gc();

					window = gp.getWindowVersion(xcoord,ycoord,width,height);
					gp2 = new Graphs(window);
					area.setIcon(new ImageIcon(gp2.getImage()));
				    }

				frame.pack();
				frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
				frame.removeMouseListener(mouse_blocker_listener);	
			    }
			});
		    toggle.setBackground(new Color(176,208,176));
		    pane.add(toggle);
		}
				     

	    JButton pen;
	    pen = new JButton(JarTools.getImage("penicon.gif"));
	    pen.setText("Pen");
	    pen.setPreferredSize(new Dimension(30,20));
	    pen.setActionCommand("Pen");
	    pen.setToolTipText("Draw.");
	    pen.addActionListener(new ActionListener ()
		{
		    public void actionPerformed (ActionEvent e)
		    {
			area.setCursor(cursor);
			drawNow = true;
		    }
		});
	    pen.setBackground(new Color(176,208,176));
	    pane.add(pen);

	    JButton eraser;
	    eraser = new JButton(JarTools.getImage("eraser.gif"));
	    eraser.setText("Eraser");
	    eraser.setActionCommand("Eraser");
	    eraser.setPreferredSize(new Dimension(30,20));
	    eraser.setToolTipText("Erase.");
	    eraser.addActionListener(new ActionListener ()
		{
		    public void actionPerformed (ActionEvent e)
		    {
			area.setCursor(cursor2);
			drawNow = false;
		    }
		});
	    eraser.setBackground(new Color(176,208,176));
	    pane.add(eraser);

	    if ((window == null) || (screen == null)) 
		{
		    JLabel empty = new JLabel(" ");
		    empty.setBackground(new Color(176,208,176));
		    pane.add(empty);
		}

	    JButton button;
	    button = new JButton("Clear Scribble");
	    button.setActionCommand("Clear");
	    button.setToolTipText("Clear all the scribble lines.");
	    button.addActionListener(this);
	    button.setBackground(new Color(176,208,176));
	    pane.add(button);

	    JButton button2;
	    button2 = new JButton("Finish Scribble");
	    button2.setActionCommand(messages.getString("Send"));
	    button2.setToolTipText("Back to Feedback form.");
	    button2.addActionListener(this);
	    button2.setBackground(new Color(176,208,176));
	    pane.add(button2);

	    JButton button3;
	    button3 = new JButton("Send");
	    button3.setActionCommand("SendNow");
	    button3.setToolTipText("Finish reporting feedback and send all information now.");
	    button3.addActionListener(this);
	    button3.setBackground(new Color(176,208,176));
	    pane.add(button3);

	    panes.add(pane);

	    container.add(panes);
	    
	    panes.setAlignmentX(Component.LEFT_ALIGNMENT);
	    label.setAlignmentX(Component.LEFT_ALIGNMENT);
	    iconarea.setAlignmentX(Component.LEFT_ALIGNMENT);
	   
	    container.setSize(container.getPreferredSize());
	    content.add(container);
	}

	/**
	 * This method will tell what the program should do when user click the buttons.
	 * @param e this is the event when user click button.
	 */
	public void actionPerformed (ActionEvent e)
	{
	    if(messages.getString("Send").equals(e.getActionCommand()))
		{
		    frame.addMouseListener(mouse_blocker_listener);
		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		    sendNow = false;
		    if (windowNow == false)
			{
			    window = gp.getWindowVersion(xcoord,ycoord,width,height);
			}
		    else
			{
			    window[0] = gp2.getScreenImage();
			    window[1] = gp2.getImage();
			    window[2] = gp2.getImage2();
			    gp.setScreenVersion(window,xcoord,ycoord,width,height);
			}
 
		    bi5 = gp.getScreenImage();
		    bi = gp.getImage();
		    bi2 = gp.getImage2();
		    bi3 = window[1];
		    bi4 = window[2];
		    bi6 = window[0];

		    details = problem_details.getText();
		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		    frame.removeMouseListener(mouse_blocker_listener);	
		    dispose();
		}
	    if ("Clear".equals(e.getActionCommand()))
		{
		    if (windowNow == false)
			{
			    gp.reset();
			    area.setIcon(new ImageIcon(gp.getScreenImage()));
			}
		    else
			{
			    gp2.reset();
			    area.setIcon(new ImageIcon(gp2.getScreenImage()));
			}
		}

	    if ("SendNow".equals(e.getActionCommand()))
		{
		    frame.addMouseListener(mouse_blocker_listener);
		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		    sendNow = true;

		    if (windowNow == false)
			{
			    window = gp.getWindowVersion(xcoord,ycoord,width,height);
			}
		    else
			{
			    window[0] = gp2.getScreenImage();
			    window[1] = gp2.getImage();
			    window[2] = gp2.getImage2();
			    gp.setScreenVersion(window,xcoord,ycoord,width,height);
			}
 
		    bi5 = gp.getScreenImage();
		    bi = gp.getImage();
		    bi2 = gp.getImage2();
		    bi3 = window[1];
		    bi4 = window[2];
		    bi6 = window[0];

		    details = problem_details.getText();
		    frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		    frame.removeMouseListener(mouse_blocker_listener);	
		    dispose();
		}
	}

	/**
	 * This method will create ImageIcon of the buffered image get from the screen shot instance.
	 * The image is screen shot whole screen size image.
	 * @return ImageIcon of the screen shot image.
	 */
	protected ImageIcon createImageIcon(boolean iswindow)
	{
	    if (iswindow == false)
		{
		    if (screen[1] == null)
			return new ImageIcon(screen[0]);
		    else
			return new ImageIcon(screen[1]);
		}
	    else
		{
		    if (window[1] == null)
			return new ImageIcon(window[0]);
		    else
			return new ImageIcon(window[1]);
		}
	}
	
	/**
	 * This is the special class, that will allows user to draw a line all over the label when 
	 * user dragged the mouse inside the area.
	 */
      	private class SelectionArea extends JLabel 
	{
	    /**
	     * This is the owner of this label.
	     */
	    private Selecting controller;
	    /**
	     * This is the x coordinate of the first point.
	     */
	    private int x1;
	    /**
	     * This is the x coordinate of the second point.
	     */
	    private int x2;
	    /**
	     * This is the y coordinate of the first point.
	     */
	    private int y1;
	    /**
	     * This is the y coordinate of the second point.
	     */
	    private int y2;
	    /**
	     * This is the flag to say that user is over the label of the screen image 
	     * and they are doing the mouse input from there.
	     */
	    private boolean ismouse;

	    /**
	     * This method will create a label with the specified image 
	     * icon and it will added with mouse listener that will
	     * allow user to draw a line all over the image.
	     * @param image image icon to be added to the label.
	     * @param controller this is the owner of this label.
	     */
	    public SelectionArea(ImageIcon image, Selecting controller) 
	    {
		super(image);
		this.controller = controller;
		setOpaque(true);
		
		MyListener myListener;
		myListener = new MyListener();
		addMouseListener(myListener);
		addMouseMotionListener(myListener);
	    } 
	    
	    /**
	     * This is the modified mouse listener that will allow user to draw
	     * a line all over the label while user dragging the mouse.
	     */
	    private class MyListener extends MouseInputAdapter 
	    {
		/**
		 * This method will make a red dot in the place where user pressed the mouse.
		 * @param e the mouse event
		 */
		public void mousePressed(MouseEvent e) 
		{
		    int x;
		    x = e.getX();
		    int y;
		    y = e.getY();
		
		    x2 = x;
		    y2 = y;
		    
		    x1 = x2;
		    y1 = y2;
		}

		/**
		 * This method will make a red line from (x1,y1) to the coordinate where
		 * the mouse is located now.
		 * @param e the mouse event.
		 */
		public void mouseDragged(MouseEvent e) 
		{
		    ismouse = true;
		    updateSize(e);
		}

		
		/**
		 * This method will make a red line from (x1,y1) to the coordinate where
		 * the mouse is located now.
		 * @param e the mouse event.
		 */
		public void updateSize(MouseEvent e) 
		{
		    int x;
		    x = e.getX();
		    int y;
		    y = e.getY();
		
		    x2 = x;
		    y2 = y;
	
		    repaint();    
		}
	    }
	    
	    /**
	     * This method will repaint all the component inside the dialog-window.
	     * It will draw a red line from (x1,y1) to (x2,y2) coordinates and
	     * updates the value of x1,y1 and the icon for the label. 
	     * @param g the graphics of this dialog-window.
	     */
	    public void paintComponent(Graphics g) 
	    {
		super.paintComponent(g);

		if (ismouse == true)
		    {
			if (windowNow == false)
			    {
				if (drawNow == true)
				    gp.drawLines(x1,y1,x2,y2);
				else
				    gp.eraseLines(x1,y1,x2,y2);
			    }
			else
			    {
				if (drawNow == true)
				    gp2.drawLines(x1,y1,x2,y2);
				else
				    gp2.eraseLines(x1,y1,x2,y2);
			    }
			
			x1 = x2;
			y1 = y2;

			if (windowNow == false)
			    {
				area.setIcon(new ImageIcon(gp.getImage()));
			    }
			else
			    {
				area.setIcon(new ImageIcon(gp2.getImage()));
			    }
			
			ismouse = false;
		    }
	    }
	}
    }
}















