package org.greenstone.gatherer.feedback;

import java.io.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.*;
import java.net.*;
import java.rmi.server.*;
import javax.imageio.*;
import java.util.Locale;
import java.util.ResourceBundle;
import java.text.MessageFormat;
import com.sun.image.codec.jpeg.*;
import javax.swing.Timer;
import org.greenstone.gatherer.Gatherer;

/**
 * This class will show the FeedbackInterface form.
 * It will allow user to described about the problem better.Here we will also take some more information available
 * in the system such as the size of the memory available and the screen size.User also could take more screenshot
 * so they will be able to say the sequence of events that lead up to the problem.
 * <br>If the user don't want to send this form, then all the information taken from this form will be deleted 
 * and user will be quitted from the Reporting Feedback sequence.
 *
 * @author Veronica Liesaputra
 */
public class FeedbackInterface extends JDialog
    implements ActionListener
{
    /**
     * This is the button user need to pressed if they want to view the files.
     * This button will be disabled when the timer is running and finish = false.
     */
    private JButton view_button;
    
    /**
     * This button means that the user finished give the information and
     * want to send it.
     */
    public JButton send_button;

    /**
     * This button means that the user don't want to send information and
     * back to normal application.
     * All the data taken start from user choose to start doing the Feedback sequence 
     * up to this point will be delete.
     */
    private JButton notsend_button; 

    /**
     * This is the text area where user can explain more about the problem.
     */
    private JTextArea problem_details;

    /**
     * This is the combo box that allow user to specify the poblem type.
     */
    private JComboBox problem_type;

    /**
     * This is the combo box that allow user to specify the urgency of the problem.
     */
    private JComboBox problem_urgency;

    /**
     * This combo box will ask whether or not user want to send the screenshot.
     */
    private JComboBox problem_screenshot;

    /**
     * This text field allow user to type the smtp address of their email that
     * they want this application to use to send all the data.
     * If they don't fill this field then it will set to the same
     * smtp adress of where the data will be send to.
     */
    private JTextField smtp_address;

    /**
     * This text field allow user to type the email adress that they want this
     * application to use to send all the data.
     * If they don't fill this field then it will set to the same email
     * adress of where the data will be send to.
     */
    private JTextField email_address;

    /**
     * This is the name of the window the user lastly used.
     * This is the name of the window where the user called to start the Feedback
     * sequence.
     */
    private String frameName;

    /**
     * This is the unique code generated for each time user start doing the Feedback
     * sequence.
     * This code will be used as reference to which feedback that the user send.
     */
    private static String code;

    /**
     * This is the date when the user start open this FeedbackInterface form.
     */
    private Date curr_date;
    
    /**
     * This is the special listener class that record all the action user did in application.
     */
    private static ActionRecorderDialog dialog;

    /**
     * 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 is the screen shot instance that will allow the application to take screen shot of the whole
     * screen or only the window that the user currently doing their action.
     */
    private ScreenShot screen;

    /**
     * This is the thread that allows the encoding of the image file to String and the saving of image to
     * a jpeg file happens concurrently.
     */
    private Thread save;

    /**
     * This is the hashmap that hold the screen shot and the panel where the screenshot is held.
     */
    private HashMap picAndPane;

    /**
     * This is the panel that hold all the panels containing the screenshots taken.
     */
    private JPanel picture_scroll;

    /**
     * This is how many rows of screenshots panel displayed at the moment.
     */
    private int row;

    /**
     * This is the array list that hold all the screenshots panel displayed.
     */
    private ArrayList paneArray;

    /**
     * This button will remove the last screenshot panels.
     */
    private JButton remove;

    /**
     * This is a reference to feedback interface displayed at the moment.
     */
    private FeedbackInterface frame;

    /**
     * This is the thread to send all the xml files back to the developer.
     */
    private Thread sendThread;

    /**
     * This is the flag to tell whether or not the sending files finished or not.
     * It is also flag to tell whether or not the viewing files finished or not.
     */
    private static boolean finish;

    /**
     * This is the timer to displayed the progress bar to tell user to wait while
     * we sending the files or while we generate the xml files to be viewed.
     * If finish = false then wait cursor,progress bar and wait label will be displayed.
     * If finish = true then default cursor will be displayed.
     */
    private Timer timer;

    /**
     * Progress bar displayed when user sending or want to view details.
     */
    private JProgressBar progressBar;

    /**
     * Label displayed to tell user to wait for a while.
     */
    private JLabel wait_lbl;

    /**
     * This is the background colour for the window.
     */
    private Color bckcolor;
    
    /**
     * This is the panel to displayed all descriptions panel.
     */
    private JPanel tempPane;

    /**
     * This is the thread that will be running when user pressed the preview button.
     * This thread will show the 6 xml files that are going to be send. It will run concurrently
     * with the timer, if value of finish = true, this thread will be null-ed.
     */
    private Thread prevThread;
    
    /**
     * This is the flag to say whether or not this window should be dispose when timer is stop
     * and finish = true.
     * If selected = true then this window should be dispose, otherwise don't dispose it.
     */
    private boolean selected = false;
    
    /**
     * This is a blocker to say that user cannot do anything while waiting.
     */
    private MouseListener mouse_blocker_listener = new MouseAdapter() {};
 
    /**
     * Will make a dialog window that allows people to write more about the problem that want
     * to send.
     * This is the GUI for user to write on Feedback form. It is also setting the up the appropriate 
     * data member with the value passed on to this constructor.
     * (Precondition: (sh != null) && (dlg != null) && (msg != null))
     * @param sh  an instance of ScreenShot that will allow application to take screenshot.
     * @param frame_name name of the window where user called Feedback form from.
     * @param msg holding the resource of the words that is stored in Messages.properties file.
     * @param dlg holding the special listener.
     */
    public FeedbackInterface(ScreenShot sh,String frame_name,
			     ResourceBundle msg,ActionRecorderDialog dlg)
    {
	super();

	frame = this;

	bckcolor = new Color(176,209,217);

	picAndPane = new HashMap();

	messages = msg;
	frameName = frame_name;
	dialog = dlg;

	FeedbackInterface.setDefaultLookAndFeelDecorated(true);
	setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
	setTitle(messages.getString("SendFeedbackForm"));
	
	screen = sh;
	Container container;
	container = getContentPane();
	createUI(container);
	curr_date = new Date();
	
	Toolkit kit;
	kit = Toolkit.getDefaultToolkit();
	Dimension screenSize;
	screenSize = kit.getScreenSize();
	int screenHeight;
	screenHeight = screenSize.height;
	int screenWidth;
	screenWidth = screenSize.width;
	Dimension size;
	size = this.getSize();
	setLocation((screenWidth - size.width - 500) , 
		    (screenHeight - size.height - 700));
	
	setBackground(bckcolor);
	pack();
	setModal(false);
	setVisible(true);
    }

    /**
     * This method is setting up the content pane for the Feedback form window.
     * (Precondition: (window != null))
     * @param window the content pane of Feedback form window. 
     */
    public void createUI(Container window)
    {
	JPanel container;
	container = new JPanel();
	container.setBackground(bckcolor);
	container.setLayout(new BoxLayout(container,BoxLayout.PAGE_AXIS));
	
	String opening_text;
	opening_text = messages.getString("FeedbackOpeningText");
	JTextArea textArea;
	textArea = new JTextArea(opening_text);
	textArea.setMinimumSize(new Dimension(100,100));
	textArea.setOpaque(false);
	textArea.setEditable(false);
	textArea.setLineWrap(true);
	textArea.setWrapStyleWord(true);
	textArea.setBorder(new EmptyBorder(10,10,0,10));
	textArea.setBackground(bckcolor);
	container.add(textArea);

	tempPane = new JPanel();
	tempPane.setLayout(new BorderLayout());
	tempPane.setBackground(new Color(176,208,176));

	paneArray = new ArrayList();
	picture_scroll = new JPanel();
	row = 1;
	picture_scroll.setLayout(new GridLayout(0,1));
	picture_scroll.setBackground(new Color(176,208,176));
	tempPane.add(picture_scroll,BorderLayout.PAGE_START);

	JPanel btnPanel;
	btnPanel = new JPanel();
	btnPanel.setBackground(new Color(176,208,176));
	remove = new JButton("Remove");
	remove.setActionCommand("Remove");
	remove.addActionListener(new ActionListener ()
	    {
		public void actionPerformed(ActionEvent e)
		{
		    Object obj;
		    JPanel pane;

		    if (paneArray.size() == 0)
			System.out.println("There is no panel here!");
		    else
			{
			    pane = (JPanel) paneArray.get((row - 2));
			    obj = picAndPane.get(pane);
			    obj = null;
			    picAndPane.remove(pane);
			    paneArray.remove((row - 2));
			    
			    if (paneArray.size() == 0)
				remove.setVisible(false);

			    picture_scroll.remove(pane);
			
			    row--;
			    
			    picture_scroll.setSize(picture_scroll.getPreferredSize());
			    picture_scroll.revalidate();
			    picture_scroll.repaint();
			    tempPane.setSize(tempPane.getPreferredSize());
			    tempPane.revalidate();
			    tempPane.repaint();
			}
		}
	    });
	remove.setToolTipText("Remove last thumbnail");
	remove.setBackground(new Color(176,208,176));
	remove.setVisible(false);
	btnPanel.add(remove);
	tempPane.add(btnPanel,BorderLayout.PAGE_END);
   
	JScrollPane pict_scroll;
	pict_scroll = new JScrollPane(tempPane);
	pict_scroll.setBackground(bckcolor);
	pict_scroll.setPreferredSize(new Dimension(300,300));
	pict_scroll.setBorder(new EmptyBorder(0,10,10,10));
	container.add(pict_scroll);

	JPanel pane;
	pane = new JPanel();
	pane.setBackground(bckcolor);
	pane.setLayout(new GridLayout(0,2));
	pane.setBorder(new EmptyBorder(10,10,10,10));
		
	JLabel txt_type;
	txt_type = new JLabel(messages.getString("Whatkindofproblemisit") + "?    ");
	txt_type.setBackground(bckcolor);
	pane.add(txt_type);
	
	String [] type = {" ",messages.getString("ContentError"),
			  messages.getString("ImageNotShow"),
			  messages.getString("StrangeBehaviour"),
			  messages.getString("SomethingUnexpectedHappen"),
			  messages.getString("HardToUse"),
			  messages.getString("Other")};
	problem_type = new JComboBox(type);
	problem_type.setOpaque(false);
	problem_type.addActionListener(this);
	problem_type.setBackground(bckcolor);
	pane.add(problem_type);

	JLabel txt_urgent;
	txt_urgent = new JLabel(messages.getString("Howbadistheproblem")+"?  ");
	txt_urgent.setBackground(bckcolor);
	pane.add(txt_urgent);

	String[] urgent = {" ",messages.getString("Critical"),
		  messages.getString("Serious"),
		  messages.getString("Medium"),messages.getString("Minor"),
		  messages.getString("Trivial")};
	problem_urgency = new JComboBox(urgent);
	problem_urgency.setOpaque(false);
	problem_urgency.addActionListener(this);
	problem_urgency.setBackground(bckcolor);
	pane.add(problem_urgency);

	/*JLabel txt_screenshot;
	txt_screenshot= new JLabel(messages.getString("Doyouwanttosendthescreenshot") + "?  ");
	txt_screenshot.setBackground(new Color(108,168,108));
	pane.add(txt_screenshot);

	String[] screenshot = {messages.getString("Yes"),
			       messages.getString("No")};
	problem_screenshot = new JComboBox(screenshot);
	problem_screenshot.addActionListener(this);
	problem_screenshot.setBackground(new Color(108,168,108));
	pane.add(problem_screenshot);*/
	
	
	/*JLabel txt_smtp;
	txt_smtp = new JLabel(messages.getString("SMTPaddress") + "?  ");
	txt_smtp.setBackground(new Color(176,208,176));
	pane.add(txt_smtp);

	smtp_address = new JTextField();
	smtp_address.setBackground(new Color(224,240,224));
	pane.add(smtp_address);*/
	

	/*JLabel txt_email;
	txt_email = new JLabel(messages.getString("Emailaddress") + "?  ");
	txt_email.setBackground(new Color(176,208,176));
	pane.add(txt_email);

	email_address = new JTextField();
	email_address.setBackground(new Color(224,240,224));
	pane.add(email_address);*/
	
	JLabel empty;
	empty = new JLabel ("   ");
	empty.setBackground(bckcolor);
	pane.add(empty);
	JLabel empty2;
	empty2 = new JLabel ("   ");
	empty2.setBackground(bckcolor);
	pane.add(empty2);
	container.add(pane);

	JPanel panely;
	panely = new JPanel();
	panely.setLayout(new GridLayout(0,3));
	panely.setBackground(bckcolor);
	panely.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
	
	view_button = new JButton("Details . . .");
	view_button.setActionCommand(messages.getString("Preview"));
	view_button.addActionListener(this);
	view_button.setToolTipText(messages.getString("ConformationPreview"));
	view_button.setBackground(bckcolor);
	panely.add(view_button); 

	send_button = new JButton(messages.getString("Send"));
	send_button.setActionCommand(messages.getString("Send"));
	send_button.addActionListener(this);
	send_button.setDefaultCapable(true);
	send_button.setToolTipText(messages.getString("FeedbackSendButton"));
	send_button.setBackground(bckcolor);
	panely.add(send_button);
	
	notsend_button = new JButton("Cancel");
	notsend_button.setActionCommand(messages.getString("NotSend"));
	notsend_button.addActionListener(this);
	notsend_button.setToolTipText(messages.getString("FeedbackNotSendButton"));
	notsend_button.setBackground(bckcolor);
	panely.add(notsend_button);
	container.add(panely);

	//Align the left edges of the components.
	textArea.setAlignmentX(Component.LEFT_ALIGNMENT);
	pict_scroll.setAlignmentX(Component.LEFT_ALIGNMENT);
	pane.setAlignmentX(Component.LEFT_ALIGNMENT);
	panely.setAlignmentX(Component.LEFT_ALIGNMENT);

	String about;
	about = messages.getString("FeedbackAboutText");
	JTextArea about_txt;
	about_txt = new JTextArea(about);
	about_txt.setEditable(false);
	about_txt.setLineWrap(true);
	about_txt.setWrapStyleWord(true);
	about_txt.setBackground(bckcolor);
	about_txt.setBorder(new EmptyBorder(10,10,10,10));

	String privacy;
	privacy = messages.getString("FeedbackPrivacyText");
	JTextArea privacy_txt;
	privacy_txt = new JTextArea(privacy);
	privacy_txt.setEditable(false);
	privacy_txt.setLineWrap(true);
	privacy_txt.setWrapStyleWord(true);
	privacy_txt.setBackground(bckcolor);
	privacy_txt.setBorder(new EmptyBorder(10,10,10,10));
 
	JTabbedPane tab;
	tab = new JTabbedPane();
	tab.setBackground(bckcolor);
	tab.addTab(messages.getString("Form"),container);
	tab.addTab(messages.getString("About"),about_txt);
	tab.addTab(messages.getString("Privacy"),privacy_txt);
	tab.setBorder(new EmptyBorder(5,5,5,5));
	
	JPanel panelx;
	panelx = new JPanel();
	panelx.setLayout(new BoxLayout(panelx,BoxLayout.PAGE_AXIS));
	panelx.setBackground(bckcolor);
	panelx.setBorder(new EmptyBorder(new Insets(10,10,10,10)));
	
	wait_lbl = new JLabel(messages.getString("Pleasewait"));
	wait_lbl.setBackground(bckcolor);
	wait_lbl.setVisible(false);
	panelx.add(wait_lbl);
	
	progressBar = new JProgressBar ();
	progressBar.setBackground(bckcolor);
	progressBar.setVisible(false);
	panelx.add(progressBar);

	JLabel emp2;
	emp2 = new JLabel ("   ");
	emp2.setBackground(bckcolor);
	panelx.add(emp2);

	wait_lbl.setAlignmentX(Component.CENTER_ALIGNMENT);
	progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
	emp2.setAlignmentX(Component.CENTER_ALIGNMENT);

	final String p1;
	final String p2;
	p1 = "Tab";
	p2 = "ProgressBar";

	final JPanel cards;
	cards = new JPanel(new CardLayout());
	cards.setBackground(bckcolor);
	cards.add(tab,p1);
	cards.add(panelx,p2);

	window.add(cards);

	
	timer = new Timer(1000, new ActionListener()
	    {
		public void actionPerformed(ActionEvent evt)
		{
		    if (finish == true)
			{
			    if (sendThread != null)
				{
				    sendThread.interrupt();
				    sendThread = null;
				}

			    if (prevThread != null)
				{
				    prevThread.interrupt();
				    prevThread = null;
				}
			    
			    Component glass_pane;
			    glass_pane = frame.getGlassPane();
			    
			    glass_pane.setVisible(false);
			    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			    glass_pane.removeMouseListener(mouse_blocker_listener);
			    
			    wait_lbl.setVisible(false);
			    progressBar.setIndeterminate(false);
			    progressBar.setVisible(false);
			    
			    frame.setTitle(messages.getString("SendFeedbackForm"));
			    
			    CardLayout cl = (CardLayout)(cards.getLayout());
			    cl.show(cards,p1);
			    
			    if (selected == true)
				frame.dispose();

			    timer.stop();
			}
		    else
			{
			    Component glass_pane;
			    glass_pane = frame.getGlassPane();
			    
			    glass_pane.addMouseListener(mouse_blocker_listener);
			    glass_pane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			    glass_pane.setVisible(true);

			    frame.setTitle("Please wait...");

			    CardLayout cl = (CardLayout)(cards.getLayout());
			    cl.show(cards,p2);

			    wait_lbl.setVisible(true);
			    progressBar.setIndeterminate(true);
			    progressBar.setVisible(true);
			}
		}
	    });
    }

    /**
     * This method will set the finish variable values.
     * When the sending files is finished, the sending application  will set the finish value to true.
     * @param fin whether or not the send files is finished.
     */
    public static void setFinish (boolean fin)
    {
	finish = fin;
    }

    /**
     * This is the class to represent the whole panel that hold the screenshot and the comments
     * about the screenshot.
     */
    private class ThumbnailPic implements Serializable
    {
	/**
	 * This is the panel that hold a thumbnail for a screenshot and a comments text area.
	 */
	private JPanel picpane;

	/**
	 * This hold the BufferedImages for the whole screen version of screenshot.
	 */
	private BufferedImage[] screenimages;

	/**
	 * This hold the BufferedImages for the window version only.
	 */
	private BufferedImage[] windowimages;

	/**
	 * This is the text area where user can enter their comments.
	 */
	private JTextArea problem_details;

	/**
	 * This is a flag to tell us which image user wants to send.Its defaults value is false.
	 * If iswindow = true then it means user wants to send the window version only.
	 * If iswindow = false then it means user wants to send the whole screen version.
	 */
	private boolean iswindow;

	/**
	 * This is the titles for the panel.
	 * Usually this is the title of the window where user wants to do the screenshot.
	 * If the title is more than 40 characters then we will trim it and add ... at the back of it.
	 */
	private String titles;

	/**
	 * This is the width of the image user wants to send.
	 */
	private String iw;

	/**
	 * This is the height of the image user wants to send.
	 */
	private String ih;

	/**
	 * This is the x-coordinate where the window located inside the whole screen image.
	 */
	private int xcoord;

	/**
	 * This is the y-coordinate where the window located inside the whole screen image.
	 */
	private int ycoord;

	/**
	 * This is the width of the window inside the whole screen image.
	 */
	private int width;

	/**
	 * This is the height of the window inside the whole screen image.
	 */
	private int height;

	/**
	 * This is the constructor that will setup the panel that contains
	 * a thumbnail screenshot and a comments text area.
	 * @param image the whole screen screenshot image.
	 * @param text  the title for this pane.
	 * @param x     the x-coordinate of the window inside the whole screen image.
	 * @param y     the y-coordinate of the window inside the whole screen image.
	 * @param w     the width of the window inside the whole screen image.
	 * @param h     the height of the window inside the whole screen  image. 
	 */
	//public ThumbnailPic (BufferedImage screen,byte[] image,String text)
	public ThumbnailPic (BufferedImage image,String text,int x,int y,int w,int h)
	{
	    xcoord = x;
	    ycoord = y;
	    width = w;
	    height = h;
	    iswindow = false;
	    titles = text;
	    screenimages = new BufferedImage[3];
	    windowimages = new BufferedImage[3];
	    //screenimages[0] = screen;
	    screenimages[0] = image;
	    screenimages[1] = null;
	    screenimages[2] = null;
	    windowimages[0] = null;
	    windowimages[1] = null;
	    windowimages[2] = null;
	    addPanel(image);
	}

	/**
	 * This method will setup the components inside the panel properly.
	 * @param image the whole screen screenshot image.
	 */
	//public void addPanel (byte[] image)
	public void addPanel (BufferedImage image)
	{
	    picpane = new JPanel();
	    picpane.setLayout(new BorderLayout());
	    
	    final JButton picture;
	    picture = new JButton();

	    int w;
	    int h;

	    w = (int) (150/2);
	    h = (int) (150/2);
	    
	    iw = "" + image.getWidth();
	    ih = "" + image.getHeight();

	    ImageIcon thumbnail;
	    thumbnail = new ImageIcon(image.getScaledInstance(w,h,Image.SCALE_SMOOTH));

	    picture.setIcon(thumbnail);
	    picture.setText("Draw . . .");
	    picture.setActionCommand("Scribble");
	    picture.addActionListener(new ActionListener()
		{
		    public void actionPerformed (ActionEvent e)
		    {
			frame.addMouseListener(mouse_blocker_listener);
			frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			SelectPicture select;
			select = new SelectPicture(screenimages,windowimages,iswindow,problem_details.getText(),messages);
			frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			frame.removeMouseListener(mouse_blocker_listener);	
			select.setWindowBounds(xcoord,ycoord,width,height);
			
			iswindow = select.getIsWindow();

			screenimages[0] = select.getImage3();
			screenimages[1] = select.getImage();
			screenimages[2] = select.getImage2();

			if (iswindow == true)
			    {
				windowimages[0] = select.getWindowImage3();
				windowimages[1] = select.getWindowImage();
				windowimages[2] = select.getWindowImage2();
			    }
			else
			    {
				windowimages[0] = null;
				windowimages[1] = null;
				windowimages[2] = null;
			    }
			
			problem_details.setText(select.getDetails());

			int w,h;
			w = (int) (150/2);
			h = (int) (150/2);
			
			ImageIcon thumbnail;

			if (iswindow == false)
			    thumbnail = new ImageIcon(screenimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH));
			else
			    thumbnail = new ImageIcon(windowimages[1].getScaledInstance(w,h,Image.SCALE_SMOOTH));

			picture.setIcon(thumbnail);
			
			if (select.getSendNow() == true)
			    {
				ActionEvent evt;
				evt = new ActionEvent(send_button,ActionEvent.ACTION_PERFORMED,messages.getString("Send"));

				frame.actionPerformed(evt);
			    }
		    }
		});
	    picture.setToolTipText("Click if you want to draw on it");
	    picture.setMargin(new Insets(5,5,5,5));
	    picture.setVerticalTextPosition(AbstractButton.BOTTOM);
	    picture.setHorizontalTextPosition(AbstractButton.CENTER);
	    picture.setBackground(new Color(176,208,176));
	    picpane.add(picture,BorderLayout.LINE_START);
	    
	    JPanel txtPane;
	    txtPane = new JPanel(new BorderLayout());
	    txtPane.setBackground(new Color(176,208,176));
	    txtPane.setBorder(new EmptyBorder(5,5,5,5));

	    JLabel lbldesc = new JLabel("Comments :");
	    lbldesc.setBackground(new Color(176,208,176));
	    txtPane.add(lbldesc,BorderLayout.PAGE_START);

	    problem_details = new JTextArea();
	    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(300,150));
	    txtPane.add(scroll,BorderLayout.LINE_START);
	   
	    picpane.setSize(new Dimension(150,150));
	    picpane.add(txtPane,BorderLayout.CENTER);
	}

	/**
	 * This method will get the width of the image user wants to send.
	 * @return the width of the image.
	 */
	public String getWidth()
	{
	    if (iswindow == false)
		return "" + screenimages[0].getWidth();
	    else
		{
		    return "" + windowimages[0].getWidth();
		}
	}

	/**
	 * This method will get the height of the image user wants to send.
	 * @return the height of the image.
	 */
	public String getHeight()
	{
	    if (iswindow == false)
		return "" + screenimages[0].getHeight();
	    else
		{
		    return "" + windowimages[0].getHeight();
		}  
	}

	/**
	 * This method will get the titles of this panel.
	 * @return the panel's title.
	 */
	public String getTitles()
	{
	    return titles;
	}

	/**
	 * This method will get user comments inside the text area.
	 * @return the user's comments.
	 */
	public String getProblemDetails ()
	{
	    String txt;
	    txt = problem_details.getText();
	    
	    if (txt == null)
		return " ";
	    else
		return txt;
	}

	/**
	 * This method will setting up the text inside the text area.
	 * @param comments the text set to the text area.
	 */
	public void setComments (String comments)
	{
	    problem_details.setText(comments);
	}

	/**
	 * This method will get the image that user wants to send.
	 * @return image going to be send.
	 */
	public BufferedImage[] getImages ()
	{
	    if (iswindow == false)
		return screenimages;
	    else
		return windowimages;
	}

	/**
	 * This method will get the non-scribble lines image that user wants to send.
	 * @return the string representation of the non-scribble lines image.
	 */
	public String getScreenImage ()
	{
	    if (iswindow == false)
		return convert(screenimages[0]);
	    else
		return convert(windowimages[1]);
	}

	/**
	 * This method will get the scribble lines image that user wants to send.
	 * @return the string representation of the scribble lines image.
	 */
	public String getScreenAndLineImage ()
	{
	    if (iswindow == false)
		{
		    if (screenimages[1]!= null)
			return convert(screenimages[1]);
		    else
			return convert(screenimages[0]);
		}
	    else
		{
		    if (windowimages[1]!= null)
			return convert(windowimages[1]);
		    else
			return convert(windowimages[0]);
		}
	}

	/**
	 * This method will get only scribble lines image that user wants to send.
	 * @return the string representation of the only scribble lines image.
	 */
	public String getLineForScreenImage ()
	{
	    if (iswindow == false)
		{
		    if (screenimages[2] != null)
			return convert(screenimages[2]);
		    else
			return "";
		}
	    else
		{
		    if (windowimages[2] != null)
			return convert(windowimages[2]);
		    else
			return "";
		}
	}

	/**
	 * This method will get the panel that hold a thumbnail and a text area.
	 * @return panel that represent the thumbnail and the text area.
	 */
	public JPanel getPanel()
	{
	    return picpane;
	}
    }

    /**
     * This method will setting up the comments to be displayed inside the latest added panel.
     * So if the window where user wants to take the screenshot at the moment is a modal window
     * then it will setting the comments to ask user to close the window before they can enter
     * their comments there.
     * @param modal the modality of the window where user wants to take the screenshot.
     */
    public void setComment (boolean modal)
    {
	if (paneArray.size() == 0)
	    System.out.println("There is no panel here!");
	else
	    {
		JPanel pane;
		pane = (JPanel) paneArray.get((row - 2));
		ThumbnailPic obj;
		obj = (ThumbnailPic) picAndPane.get(pane);
		String text;
		if (modal == true)
		    text = "Please close '" + obj.getTitles() + "' window \nbefore you can enter comments here.";
		else
		    text = " ";
		obj.setComments(text);
	    }
    }

    /**
     * This method will add a panel that contains the thumbnail button and the text area.
     * @param title the window's title.
     * @param image the whole screen image.
     * @param x     the window's x-coordinate in the image.
     * @param y     the window's y-coordinate in the image.
     * @param width the window's width in the image.
     * @param height the window's height in the image.
     */
    //public void addScreenPanel (String title,BufferedImage screen,byte[] image)
    public void addScreenPanel (String title,BufferedImage image,int x,int y,int width,int height)
    {
	final JPanel pane;
	pane = new JPanel();
	pane.setLayout(new BorderLayout());
	pane.setBackground(new Color(176,208,176));

	Border loweredetched;
	loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);

	String ttl;
	if (title.length() > 41)
	    ttl = title.substring(0,40) + "  . . . ";
	else
	    ttl = title;

	TitledBorder border;
	border = BorderFactory.createTitledBorder(loweredetched, title);
	border.setTitleJustification(TitledBorder.LEFT);
	
	pane.setBorder(BorderFactory.createCompoundBorder(new EmptyBorder(5,5,5,5),border));
	
	ThumbnailPic pic;
	//pic = new ThumbnailPic(screen,image,title);
	pic = new ThumbnailPic(image,title,x,y,width,height);
	picAndPane.put(pane,pic);
	pane.add(pic.getPanel(),BorderLayout.LINE_START);

	remove.setVisible(true);
	picture_scroll.add(pane);
	paneArray.add(pane);
	row++;
	picture_scroll.setSize(picture_scroll.getPreferredSize());
	picture_scroll.revalidate();
	picture_scroll.repaint();
	tempPane.setSize(tempPane.getPreferredSize());
	tempPane.revalidate();
	tempPane.repaint();
    }

    /**
     * This method will generate the unique code that will be used as the 
     * reference number of the feedback that user are about to send.
     * @return the unique code.
     */
    public String getPrevData ()
    {
	try
	    {
		UID id = new UID();
		code =  "" + InetAddress.getLocalHost().hashCode() + id.hashCode();
	    }
	catch (UnknownHostException exp) {}
	return code;
    }

    /**
     * This method allows another class to get the unique code that can be used as 
     * the reference number of the feedback that user are about to send.
     * This method should be called only if 
     * getPrevData() method already been called before.Otherwise it will return null. 
     * @return the unique code
     */
    public static String getCode()
    {
	return code;
    }

    /**
     * This method will encode BufferedImage into their String representation using
     * Base64 encoder.
     * (Precondition: (image != null))
     * @param image is the image that we want to encode to String.
     */
    public String convert (BufferedImage image)
    {
	String txt;
	txt = null;

	try
	    {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		ImageIO.write(image,"jpeg",stream);
		byte[] bytes = stream.toByteArray();

		txt = Base64.encodeBytes(bytes);
		
	    }
	catch(IOException ex) {}

	return txt;
    }

    /**
     * This method is to make sure that there is no thread running at the moment.
     */
    private void ensureEventThread()
    {
	if(SwingUtilities.isEventDispatchThread())
	    {
		return;
	    }
	throw new RuntimeException(messages.getString("file"));
    }

    /**
     * This method will create all 6 xml files, jarred them into one file, deletes all xml files and
     * sending it.
     * The xml files for:
     * <br> 1.The history & information of all the actions done and windows opened by the application
     *        after user choose to start the sequence of sending feedback.
     * <br> 2.The history of all the commands (actions) done by the user before choosing
     *        after start the sequence of sending feedback.
     * <br> 3.The informations we get from the feedback interface form period.
     * <br> will be getting from vector and the temp_feedbackhist.log file.
     * (Precondition: (sx != null) && (vector != null) && (err_array != null))
     * @param sx the xml parser.
     * @param vector the vector that hold the history and information.
     * @param err_array the arrays of information we take from the feedback interface period.
     * @param imgFile   the arrays of information we take from the panels inside feedback interface form.
     */
    private void sendState (SaveToXML sx,Vector vector,String[] err_array,String[] imgFile)
    {
	String dirname;
	dirname = "xmlfeedback/";
	
	File dir = new File("xmlfeedback");
	if (dir.isDirectory() == false)
	    dir.mkdir();

	sx.saveFeedback(err_array,imgFile);
	
	sx.open(dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml",
		"HISTORY");
	SaveToXML sx2;
	sx2 = new SaveToXML(messages);
	sx2.open(dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml",
		 "COMMANDS");
	
	for (int i = 0 ; i < vector.size() ; i++)
	    {
		History log;
		log = (History) vector.get(i);
		log.sendXML(sx);
		log.sendXMLComm(sx2);
	    }
	
	Vector stack;
	stack = getPrev_log();
	if (stack != null)
	    {
		for (int i = 0 ; i < stack.size() ; i++)
		    {
			History log;
			log = (History) stack.get(i);
			log.sendXML(sx);
			log.sendXMLComm(sx2);
		    }
		stack.removeAllElements();
		System.gc();
		stack = null;
	    }
	
	sx2.close("COMMANDS");
	sx.close("HISTORY");
	
	getHistPrev_log(sx,sx2);
	
	ZipFile zip;
	zip = new ZipFile();
	zip.sendZipXMLFile();

	File f;
	f = new File (dirname + "feedback" + FeedbackInterface.getCode() + ".xml");
	f.delete();
	f = new File (dirname + "feedbackcontent" + FeedbackInterface.getCode() + ".xml");
	f.delete();
	f = new File (dirname + "feedbackcommand" + FeedbackInterface.getCode() + ".xml");
	f.delete();
	/*f = new File (dirname + "content" + FeedbackInterface.getCode() + ".xml");
	  f.delete();*/
	f = new File (dirname + "command" + FeedbackInterface.getCode() + ".xml");
	f.delete();
	
	String[] args = new String[5];
	args[0] = "vl6@cs.waikato.ac.nz";
	args[1] = dirname + "Jar" + FeedbackInterface.getCode() + "File.jar";
	args[4] = "lib/parser.jar";
	args[2] = err_array[19];
	args[3] = err_array[20];
	SendHTTP sm = new SendHTTP();
	//SendMail sm = new SendMail();
	sm.sendMail(args,messages,FeedbackInterface.getCode());
    }
	
    /**
     * This method will create the 2 xml files.
     * The xml files are:
     * <br> 1.The history & information of all the actions done and windows opened by the application
     *         before user choose to start the sequence of sending feedback.
     * <br> 2.The history of all the commands (actions) done by the user before choosing
     *         to start the sequence of sending feedback.
     * <br> The information will be getting from history.log file and the temp_history.log file.
     * (Precondition: (sx != null) && (sx2 != null))
     * @param sx the xml parser for the history xml file.
     * @param sx2 the xml parser for the command xml file.
     */
    private void getHistPrev_log(SaveToXML sx,SaveToXML sx2)
    {
	Vector stack = null;
	try
	    {
		File f = new File("history.log");
		if (f.exists() == true)
		    {
			FileInputStream fis = new FileInputStream(f);
			ObjectInputStream ois = new ObjectInputStream(fis);
			
			stack = (Vector) ois.readObject();
			
			String dirname;
			dirname = "xmlfeedback/";

			/*sx.open(dirname + "content" + FeedbackInterface.getCode() + ".xml",
			  "HISTORY");*/
			sx2.open(dirname + "command" + FeedbackInterface.getCode() + ".xml",
				 "COMMANDS");
			
			if (stack != null)
			    {
				for (int i = 0 ; i < stack.size() ; i++)
				    {
					History log;
					log = (History) stack.get(i);
				        //log.sendXML(sx);
					log.sendXMLComm(sx2);
				    }
				stack.removeAllElements();
				System.gc();
				stack = null;
			    }
			
			stack = (Vector) ois.readObject();
			
			if (stack != null)
			    {
				for (int i = 0 ; i < stack.size() ; i++)
				    {
					History log;
					log = (History) stack.get(i);
				        //log.sendXML(sx);
					log.sendXMLComm(sx2);
				    }
				stack.removeAllElements();
				System.gc();
				stack = null;
			    }
			
			sx2.close("COMMANDS");
			//sx.close("HISTORY");
			
			ois.close();
		    }
	    }
	catch (IOException exp) {exp.printStackTrace();}
	catch (ClassNotFoundException exp2)
	    {
		System.out.println("class exp");}
    }

    /**
     * This method will get the Vector stored in temp_feedbackhist.log file.
     * @return the vector stored in temp_feedbackhist.log file.
     */
    public Vector getPrev_log()
    {
	Vector stack = null;
	try
	    {
		File f = new File("temp_feedbackhist.log");
		if (f.exists() == true)
		    {
			FileInputStream fis = new FileInputStream(f);
			ObjectInputStream ois = new ObjectInputStream(fis);
			stack = (Vector) ois.readObject();
			ois.close();
			return stack;
		    }
		else
		    stack = null;
	    }
	catch (IOException exp) {exp.printStackTrace();}
	catch (ClassNotFoundException exp2)
	    {
		System.out.println("class exp");}
	
	return stack;
    }

    /**
     * This is the thread that will start when user click send button and it will
     * make 6 xml files,jarred them together into 1 jar file, deletes the 6 xml files and send it.
     * @param vector the vector stored the current actions history.
     * @param err_array the array that stored all the information took during feedback interface period.
     * @param imgFile the array of that stored all the information from all the panels inside feedback interface form.
     */
    public void sendMethod (final Vector vector,final String err_array[], final String imgFile[])
    {
	ensureEventThread();
	Runnable sendRun;
	sendRun = new Runnable()
	    {
		public void run ()
		{
		    finish = false;
		    selected = true;
		    SaveToXML sx;
		    sx = new SaveToXML(messages);
		    sendState(sx,vector,err_array,imgFile);
		    finish = true;
		}
	    };
	sendThread = new Thread(sendRun);
	sendThread.start();
    }

    /**
     * This method will called the window that will display the preview of all
     * the file going to be send.
     * @param vector the vector stored the current actions history.
     * @param err_array the array that stored all the information took during feedback interface period.
     * @param imgFile the array of that stored all the information from all the panels inside feedback interface form.
     */
    public void viewMethod (final Vector vector,final String err_array[], final String imgFile[])
    {
	ensureEventThread();
	Runnable prevRun;
	prevRun = new Runnable()
	    {
		public void run ()
		{
		    finish = false;
		    selected = false;
		    ReportDetails rd;
		    rd = new ReportDetails(vector,err_array,imgFile,messages,true);
		    finish = true;
		}
	    };
	
	prevThread = new Thread(prevRun);
	prevThread.start();
    }

    /**
     * This method will save a BufferedImage to a jpeg file with the specified filename.
     * This method is a thread that will caused the thread save to be started and stop
     * if the saving process is finished.
     * (Precondition: (I != null))
     * @param I is the BufferedImage that we want to save.
     * @param picScreen name of the jpeg file where we want to store the BufferedImage
     */
    public void saveGraph(final BufferedImage I,final String picScreen)
    {
	ensureEventThread();
	Runnable saveRun;
	saveRun = new Runnable ()
	    {
		public void run()
		{
		    try 
			{
			    File file;
			    file = new File(picScreen);
			    FileOutputStream out;
			    out = new FileOutputStream(file);
			    
			    JPEGImageEncoder encoder;
			    encoder = JPEGCodec.createJPEGEncoder(out);
			    JPEGEncodeParam param;
			    param = encoder.getDefaultJPEGEncodeParam(I);
			    param.setQuality(1.0f, false);
			    encoder.setJPEGEncodeParam(param);
			    encoder.encode(I);
			    out.close();
			    save = null;
			} 
		    catch (Exception ex) {}
		}
	    };
	
	save = new Thread(saveRun);
	save.start();
    }

    /**
     * This method will get all the informations from the all the panels inside the feedback interface form.
     * @return the arrays of information from all the panels.
     */
    public String[] getimgFile()
    {
	String[] imgFile;	
	imgFile = null;

	/*String answer;
	  answer = (String) problem_screenshot.getSelectedItem();
	  if(answer == messages.getString("Yes"))
	  {*/
	
	if (paneArray.size() > 0)
	    {
		imgFile = new String[(paneArray.size() * 10)];
		
		int step;
		for (step = 0 ; step < (paneArray.size()*10) ; step=step+10)
		    {
			JPanel pane;
			ThumbnailPic obj;
			pane = (JPanel) paneArray.get((step/10));
			obj = (ThumbnailPic) picAndPane.get(pane);
			
			//obj.setSize();
			
			String title;
			title = obj.getTitles();
			
			imgFile[step+0] = title;
			imgFile[step+1] = obj.getScreenImage();
			title = "Window" + pane.hashCode() + "File";
			imgFile[step+2] = messages.getString("screen")+title+step+".jpg";
			imgFile[step+3] = obj.getScreenAndLineImage();
			imgFile[step+4] = messages.getString("ErrorLineAnd")+imgFile[step+2];
			imgFile[step+5] = obj.getLineForScreenImage();
			imgFile[step+6] = messages.getString("ErrorLineFor")+imgFile[step+2];
			imgFile[step+7] = obj.getWidth();
			imgFile[step+8] = obj.getHeight();
			imgFile[step+9] = obj.getProblemDetails();
		    }
	    }
		
	return imgFile;
    }

    /**
     * This method will get all the informations taken during feedback interface period, such as os version.
     * @return then arrays of informations.
     */
    public String[] geterr_array()
    {
	String[] err_array;
	err_array = null;

	String os_name;
	os_name = System.getProperty("os.name") + " " + System.getProperty("os.version") 
	    + " " + System.getProperty("os.arch");
	
	Date problem_date;
	String err_date,java_info,screen_res;
	problem_date = new Date();
	err_date = problem_date.toString();
	java_info = System.getProperty("java.vendor")+ " " + System.getProperty("java.class.version");
	Dimension dim;
	dim = Toolkit.getDefaultToolkit().getScreenSize();
	screen_res = "" + dim.width + "x" + dim.height;
	
	try
	    {
		err_array = new String[24];

		err_array[0] = code;
		err_array[1] = frameName;
		err_array[2] = "";
		err_array[3] = (String) problem_type.getSelectedItem();
		err_array[4] = (String) problem_urgency.getSelectedItem();
		err_array[5] = System.getProperty("user.name");
		err_array[6] = System.getProperty("user.home");
		err_array[7] = System.getProperty("user.dir");
		err_array[8] = curr_date.toString();
		err_array[9] = err_date;
		err_array[10] = os_name;
		err_array[11] = java_info;
		err_array[12] = "" + Locale.getDefault();
		err_array[13] = Gatherer.PROGRAM_NAME + " " + Gatherer.PROGRAM_VERSION; 
		err_array[14] = InetAddress.getLocalHost().getHostName();
		err_array[15] = InetAddress.getLocalHost().getHostAddress();
		err_array[16] = screen_res;
		err_array[17] = "";
		
		/*String test_txt;
		  test_txt = smtp_address.getText();
		  if ((test_txt == null)||(test_txt.length() < 5))*/
		err_array[19] = "mail.waikato.ac.nz";
		/*else
		  err_array[19] = test_txt;
		  
		  test_txt = email_address.getText();
		  if ((test_txt == null)||(test_txt.length() < 5))*/
		err_array[20] = "vl6@cs.waikato.ac.nz";
		//else
		//err_array[20] = test_txt;
		
		Runtime run;
		run = Runtime.getRuntime();
		err_array[21] = formatFileSize(run.totalMemory());
		err_array[22] = formatFileSize(run.maxMemory());
		err_array[23] = formatFileSize(run.freeMemory());
	    }
	catch(UnknownHostException exp) {}

	return err_array;
    }

    /**
     * This method will format the file size given into more elegant form,e.g. 2KB
     * @param length the file size.
     * @return the more elegant string representations of the file size.
     */
    public String formatFileSize(long length) 
    {
	String BYTE_SUFFIX;
	BYTE_SUFFIX = " B";
	long GIGABYTE;
	GIGABYTE = 1024000000l;
	String GIGABYTE_SUFFIX;
	GIGABYTE_SUFFIX = " GB";
	long KILOBYTE;
	KILOBYTE = 1024l;
	String KILOBYTE_SUFFIX;
	KILOBYTE_SUFFIX = " KB";
	long MEGABYTE;
	MEGABYTE = 1024000l;
	String MEGABYTE_SUFFIX;
	MEGABYTE_SUFFIX = " MB";

	StringBuffer result;
	result = new StringBuffer("");
	float number;
	number = 0f;
	String suffix;
	suffix = null;
	
	if(length >= GIGABYTE) 
	    {
		number = (float) length / (float) GIGABYTE;
		suffix = GIGABYTE_SUFFIX;
	    }
	else if(length >= MEGABYTE) 
	    {
		number = (float) length / (float) MEGABYTE;
		suffix = MEGABYTE_SUFFIX;
	    }
	else if(length >= KILOBYTE) 
	    {
		number = (float) length / (float) KILOBYTE;
		suffix = KILOBYTE_SUFFIX;
	    }
	else 
	    {
		return length + BYTE_SUFFIX;
	    }
	
	String number_str;
	number_str = Float.toString(number);
	char number_char[] = number_str.toCharArray();
	int pos,i;
	pos = 0;
	
	while(number_char != null && pos < number_char.length && number_char[pos] != '.')
	    {
		result.append(number_char[pos]);
		pos++;
	    }

	if(pos < number_char.length) 
	    {
		result.append(number_char[pos]);
		pos++;
		
		for(i = 0; i < 2 && pos < number_char.length; i++, pos++)
		    result.append(number_char[pos]);
	   
		while(pos < number_char.length && number_char[pos] != 'E') 
		    pos++;
	   
		while(pos < number_char.length) 
		    {
			result.append(number_char[pos]);
			pos++;
		    }
	    }
	
	result.append(suffix);
	
	return result.toString();
    }

    /**
     * This method will decide what action should be done if the user entered a button in
     * the Feedback form.
     * <br>If user click cancel button then all the information taken in this form will be deleted
     * and user will be quitted from the Reporting Feedback sequence.
     * <br>If user click the send button then all the information taken will be stored in array which
     * then will be saved into xml files and sent when user confirm to send all the files.
     * <br>If user click the details button then they can view all the xml files that are going to be send.
     * @param e the button that user clicked
     */
    public void actionPerformed (ActionEvent e)
    {
	getPrevData();

	if(messages.getString("Send").equals(e.getActionCommand()))
	    {
		String[] imgFile;
		String[] err_array;

		imgFile = getimgFile();
		err_array = geterr_array();

		timer.start();
		
		sendMethod(dialog.getVector(),err_array,imgFile);
	    }

	if(messages.getString("Preview").equals(e.getActionCommand()))
	    {
		String[] imgFile;
		String[] err_array;

		imgFile = getimgFile();
		err_array = geterr_array();

		timer.start();
		
		viewMethod(dialog.getVector(),err_array,imgFile); 
	    }

	if(messages.getString("NotSend").equals(e.getActionCommand()))
	    {
		dispose();
	    }
    }
}
	
	

	






