import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.WindowConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * Window containing the results of stamping
 * 
 * @author 413
 *
 */
public class WindowResult extends JFrame implements ActionListener
{
	private boolean loaded = false;
	private static final long serialVersionUID = 1L;
	private DefaultListModel<Job> listJob; // the list that contain the jobs
	private JList<Job> jobs; // contain the list that contain the jobs
	private DefaultListModel<Error> listErrors; // the list that contain the errors
	private JList<Error> errors; // contain the list that contain the errors
	private int currentPage = 0; // contain the list that contain the errors
	private JLabel image;

	/**
	 * Constructor
	 * 
	 * @param listJob
	 */
	WindowResult()
	{
		// ==========================loading job and results===================================
		listJob = new DefaultListModel<Job>();

		/*
		 * a filter to get only XML files
		 */
		FilenameFilter filterXML = new FilenameFilter()
		{
			public boolean accept(File arg0, String arg1)
			{
				return arg1.endsWith(".xml");
			}
		};
		File repertoire = ServiceConfig.job;
		File[] children = repertoire.listFiles(filterXML);
		for (int i = 0; i < children.length; i++)
		{
			listJob.addElement(Job.load(children[i]));
		}

		// ====================================COMPONENT================================================================
		JLabel text0 = new JLabel("Jobs:");
		JLabel text1 = new JLabel("Pages:");
		JButton open = new JButton("Open Pdf");
		JButton validate = new JButton("Correction done");
		JButton cancel = new JButton("Cancel");
		JButton screen = new JButton("Open ScreenShot");
		JButton problem = new JButton("Report a problem");
		//JButton prev = new JButton("Previous");
		//JButton next = new JButton("Next");
		// imageBox = new JPanel();
		image = new JLabel();
		JScrollPane imageBox = new JScrollPane(image);

		jobs = new JList<Job>(listJob);
		JScrollPane listjobs = new JScrollPane(jobs);
        jobs.setCellRenderer(new ListCellRenderer<Job>()
        {
			protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
        	public Component getListCellRendererComponent(JList<? extends Job> list, Job job, int index, boolean isSelected, boolean cellHasFocus)
        	{
				JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, job, index, isSelected, cellHasFocus);
				
	        	renderer.setText(job.getPDFSource().getName() + " || " + job.getResult().getGeneralError() + " || " + job.getResult().getPageErrorCount() + " errors"); 
				if(job.getResult().getGeneralError().equals("No Error"))
				{
					if(job.getResult().getPageErrorCount()>0)
					{
						if(isSelected)
						{
							renderer.setBackground(new Color(150, 150, 100));
						}
						else
						{
							renderer.setBackground(new Color(200, 200, 100));
						}
					}
				}
				else
				{
					if(isSelected)
					{
						renderer.setBackground(new Color(150, 100, 100));
					}
					else
					{
						renderer.setBackground(new Color(200, 100, 100));
					}
				}
        		return renderer;
        	}

        });

		listErrors = new DefaultListModel<Error>();

		errors = new JList<Error>(listErrors);
        errors.setCellRenderer(new ListCellRenderer<Error>()
        {
			protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
			public Component getListCellRendererComponent(JList<? extends Error> list, Error value, int index, boolean isSelected, boolean cellHasFocus)
        	{
				JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
				if(value.getLevel()==0)
				{
		        	renderer.setText("Page " + value.getErrorPageNumber() + " : " + value.getErrorDescription()); 

				}
				else
				{
					renderer.setText("Error Page " + value.getErrorPageNumber() + " : " + value.getErrorDescription());
				}
				switch(value.getLevel())
				{
					case 0 : 
						renderer.setText("Page " + value.getErrorPageNumber() + " : " + value.getErrorDescription());
						break;
						
					case 1 : 
						if(isSelected)
						{
							renderer.setBackground(new Color(150, 100, 100));
						}
						else
						{
							renderer.setBackground(new Color(200, 100, 100));
						}
						renderer.setText("Error Page " + value.getErrorPageNumber() + " : " + value.getErrorDescription());
						break;
						
					case 2 : 
						if(isSelected)
						{
							renderer.setBackground(new Color(150, 150, 100));
						}
						else
						{
							renderer.setBackground(new Color(200, 200, 100));
						}
						renderer.setText("Warning Page " + value.getErrorPageNumber() + " : " + value.getErrorDescription());
						break;
				}
        		return renderer;
        	}

        });
		JScrollPane listerreur = new JScrollPane(errors);

		// ====================================LAYOUT===================================================================
		GroupLayout layout = new GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setAutoCreateGaps(true);
		layout.setAutoCreateContainerGaps(true);
		layout.setHorizontalGroup(layout
				.createSequentialGroup()
				.addGroup(
						layout.createParallelGroup(GroupLayout.Alignment.LEADING)
								.addComponent(text0)
								.addComponent(listjobs, 0, 440 ,440)
								.addComponent(text1)
								.addComponent(listerreur, 0, 440, 440)
								.addGroup(layout.createSequentialGroup().addComponent(open).addComponent(validate).addComponent(cancel).addComponent(screen)))
				.addGroup(
						layout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(imageBox)
								.addGroup(layout.createSequentialGroup().addComponent(problem))));
		layout.setVerticalGroup(layout
				.createSequentialGroup()
				.addGroup(
						layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
								.addComponent(imageBox)
								.addGroup(
										layout.createSequentialGroup().addComponent(text0).addComponent(listjobs).addComponent(text1).addComponent(listerreur)))
					.addGroup(
						layout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(open).addComponent(validate).addComponent(cancel)
								.addComponent(screen).addComponent(problem)));

		// ====================================FRAME============================================================
		setTitle("Result");
		pack();
		setSize(1000, 600);
		setLocationRelativeTo(null);
		setVisible(true);
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		// ====================================LISTENER=========================================================
		validate.addActionListener(this);
		cancel.addActionListener(this);
		open.addActionListener(this);
		screen.addActionListener(this);
		problem.addActionListener(this);
		//prev.addActionListener(this);
		//next.addActionListener(this);
		jobs.addListSelectionListener(new ListSelectionListener()
		{
			public void valueChanged(ListSelectionEvent e)
			{
				loaded = false;
				// change List error
				listErrors.removeAllElements();
				if (jobs.getSelectedIndex() == -1)
				{
					listErrors = new DefaultListModel<Error>();
				}
				else
				{
					Job temp = listJob.getElementAt(jobs.getSelectedIndex());
					for (int i = temp.getStartPage(); i < temp.getStartPage() + temp.getResult().getPageProcessCount(); i++)
					{
						listErrors.addElement(new Error(i, "ok", 0));
					}
					for (int i = 0; i < temp.getResult().getErrors().size(); i++)
					{
						// listErrors.addElement(temp.getResult().getErrors().getElementAt(i));
						/*listErrors.setElementAt("Error page " + temp.getResult().getErrors().getElementAt(i).getErrorPageNumber() + " : "
								+ temp.getResult().getErrors().getElementAt(i).getErrorDescription(), temp.getResult().getErrors().getElementAt(i)
								.getErrorPageNumber()
								- temp.getStartPage());*/
						listErrors.setElementAt(temp.getResult().getErrors().getElementAt(i), temp.getResult().getErrors().getElementAt(i).getErrorPageNumber() - temp.getStartPage());

					}
				}

				// change image
				currentPage = listJob.getElementAt(jobs.getSelectedIndex()).getStartPage();
				loaded = true;
				errors.setSelectedIndex(0);
			}
		});
		errors.addListSelectionListener(new ListSelectionListener()
		{
			public void valueChanged(ListSelectionEvent e)
			{
				if (loaded)
				{
					currentPage = errors.getSelectedIndex() + listJob.getElementAt(jobs.getSelectedIndex()).getStartPage();

					try
					{
						BufferedImage i = ImageIO.read(new File(ServiceConfig.image + "\\"
								+ listJob.getElementAt(jobs.getSelectedIndex()).getPDFSource().getName() + currentPage + ".jpg")), temp = new BufferedImage(i
								.getWidth() / 2, i.getHeight() / 2, BufferedImage.TRANSLUCENT);
						Graphics2D g2d = (Graphics2D) temp.createGraphics();
						g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
						g2d.drawImage(i, 0, 0, i.getWidth() / 2, i.getHeight() / 2, null);
						g2d.dispose();
						image.setIcon(new ImageIcon(temp));
					}
					catch (IOException e2)
					{
						e2.printStackTrace();
					}

				}
			}
		});
	}

	/**
	 * catch events
	 */
	public void actionPerformed(ActionEvent event)
	{
		switch (event.getActionCommand())
		{
		case "Open Pdf":
			// open a pdf
			try
			{
				if (jobs.getSelectedIndex() != -1)
				{
					MacroMethods.openPdf(new File(ServiceConfig.destination.getPath() + "\\"
							+ listJob.getElementAt(jobs.getSelectedIndex()).getPDFSource().getName()));
				}
				else
				{
					JOptionPane.showMessageDialog(null, "No result selected", "impossible operation", JOptionPane.WARNING_MESSAGE);
				}
			}
			catch (Exception e1)
			{
				e1.printStackTrace();
			}
			// JOptionPane.showMessageDialog(null,"Ouverture d'un pdf (prochainement)","ouverture",JOptionPane.WARNING_MESSAGE);
			break;

		case "Open ScreenShot":
			// open a pdf
			try
			{
				if (errors.getSelectedIndex() != -1)
				{
					Boolean found = false;
					int i = 0;
					DefaultListModel<Error> temp = listJob.getElementAt(jobs.getSelectedIndex()).getResult().getErrors();
					while (i < temp.size() && !found)
					{
						found = temp.get(i).getErrorPageNumber() == errors.getSelectedIndex() + listJob.getElementAt(jobs.getSelectedIndex()).getStartPage();
						i++;
					}
					if (found)
					{
						MacroMethods.openPdf(temp.get(i - 1).getScreen());
					}
					else
					{
						JOptionPane.showMessageDialog(null, "Not an error", "impossible operation", JOptionPane.WARNING_MESSAGE);
					}
				}
				else
				{
					JOptionPane.showMessageDialog(null, "No result selected", "impossible operation", JOptionPane.WARNING_MESSAGE);
				}
			}
			catch (Exception e1)
			{
				e1.printStackTrace();
			}
			break;

		case "Correction done":
			FilenameFilter filterXML = new FilenameFilter()
			{
				public boolean accept(File arg0, String arg1)
				{
					return arg1.endsWith(".xml");
				}
			};
			// delete job.xml files
			File folder = ServiceConfig.job;
			File[] children = folder.listFiles(filterXML);
			for (int i = 0; i < children.length; i++)
			{
				System.out.println(children[i].delete());
			}
			// delete result.xml files
			folder = new File("Result");
			children = folder.listFiles(filterXML);
			for (int i = 0; i < children.length; i++)
			{
				System.out.println(children[i].delete());
			}
			// delete Image folder
			folder = ServiceConfig.image;
			children = folder.listFiles(filterXML);
			for (int i = 0; i < children.length; i++)
			{
				System.out.println(children[i].delete());
			}
			dispose();
			break;

		case "Cancel":
			// switch to manageJob window
			new WindowManageJobs(listJob);
			dispose();
			break;

		case "Report a problem":
			FilenameFilter filterJPG = new FilenameFilter()
			{
				public boolean accept(File arg0, String arg1)
				{
					return arg1.endsWith(".xml");
				}
			};
			try
				{
				File dest = ServiceConfig.image;
				dest = new File(dest.getParent()+"\\Image"+new Date().toString().replace(":","_"));
				System.out.println(dest.getAbsolutePath());
				dest.mkdir();
				// duplicate jpg files
				File folderI = ServiceConfig.image;
				File[] childrenI = folderI.listFiles(filterJPG);
				for (int i = 0; i < childrenI.length; i++)
				{
	
						copy(childrenI[i], new File(dest + "\\" + childrenI[i].getName()));
				}
			}
			catch (ErrorException e)
			{
				JOptionPane.showMessageDialog(null, e.getMessage(), "error", JOptionPane.WARNING_MESSAGE);
			}
			break;
			/*
		case "Previous":
			if (jobs.getSelectedIndex() != -1)
			{
				if (currentPage == listJob.getElementAt(jobs.getSelectedIndex()).getStartPage())
				{
					// currentPage = listJob.getElementAt(jobs.getSelectedIndex()).getLastPage();
					errors.setSelectedIndex(listErrors.size() - 1);
				}
				else
				{
					currentPage--;
					errors.setSelectedIndex(errors.getSelectedIndex() - 1);
				}
			}
			break;

		case "Next":
			if (jobs.getSelectedIndex() != -1)
			{
				if (currentPage == listJob.getElementAt(jobs.getSelectedIndex()).getLastPage())
				{
					// currentPage = listJob.getElementAt(jobs.getSelectedIndex()).getStartPage();
					errors.setSelectedIndex(0);
				}
				else
				{
					currentPage++;
					errors.setSelectedIndex(errors.getSelectedIndex() + 1);
				}
			}
			break;*/
		default:
			JOptionPane.showMessageDialog(null, "An unknown event occurred");
		}

	}

	
	/**
	 * create a copy of the source into destination file
	 */
	public static void copy(File source, File destination) throws ErrorException
	{
		try
		{
			java.io.FileInputStream sourceFile = new FileInputStream(source);
	 
			try
			{
				java.io.FileOutputStream destinationFile = new FileOutputStream(destination);
	 
				try
				{
	 
					byte buffer[] = new byte[512 * 1024];
					int nbLecture;
	 
					while ((nbLecture = sourceFile.read(buffer)) != -1)
					{
						destinationFile.write(buffer, 0, nbLecture);
					}
				} catch(Exception e) 
		        {
		        	throw new ErrorException("106 : "+e.getMessage(), 100);
		        }
				finally
				{
					destinationFile.close();
				}
			} catch(Exception e) 
	        {
	        	throw new ErrorException("107 : "+e.getMessage(), 100);
	        }
			finally
			{
				sourceFile.close();
			}
		}
		catch (IOException e)
		{
			throw new ErrorException("07 : "+e.getMessage(), 1);
		}
	}
}
