import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;


public class ServiceProcess
{
	static Logger logger = Logger.getLogger(ServiceProcess.class.getName());
	public static BufferedImage fusion(BufferedImage i1, BufferedImage i2) throws ErrorException
	{
		
	    // The images must be the same size.
	    if (i1.getWidth() == i2.getWidth() && i1.getHeight() == i2.getHeight()) 
	    {
	    	BufferedImage ret = new BufferedImage(i1.getWidth(), i1.getHeight(), BufferedImage.TYPE_INT_RGB);
	        for (int y = 0; y < i1.getWidth(); y++) 
	        {
	            for (int x = 0; x < i1.getHeight(); x++) 
	            {
	            	int darker;
	            	Color c1, c2;
	            	c1 = new Color(i1.getRGB(x, y));
	            	c2 = new Color(i2.getRGB(x, y));
	            	
	            	darker = c1.getRed();
	            	if(c1.getBlue()<darker)
	            		darker = c1.getBlue();
	            	if(c1.getGreen()<darker)
	            		darker = c1.getGreen();
	            	if(c2.getRed()<darker)
	            		darker = c2.getRed();
	            	if(c2.getBlue()<darker)
	            		darker = c2.getBlue();
	            	if(c2.getGreen()<darker)
	            		darker = c2.getGreen();
	            	Color cret = new Color(darker, darker, darker);
	            	ret.setRGB(x, y , cret.getRGB());
	            }
	        }
	    	return ret;
	    }
	    else 
	    {
        	throw new ErrorException("10 : the two screenshot don't have the same format", 1);
	    	//JOptionPane.showMessageDialog(null, "the two screenshot don't have the same format", "Error : screenshot", JOptionPane.WARNING_MESSAGE);
	        //return new Rectangle(0, 0, 0, 0);
	    }
		
	}
	
	/**
	 * Compares two images pixel by pixel to find out the stamp.
	 *
	 * @param imgA - the first image.
	 * @param imgB - the second image.
	 * @return the rectangle containing the stamp
	 */
	public static Rectangle compareImages(BufferedImage imgA, BufferedImage imgB, File save) throws ErrorException
	{
		logger.info("comparing images");
	    // The images must be the same size.
	    if (imgA.getWidth() == imgB.getWidth() && imgA.getHeight() == imgB.getHeight()) 
	    {
			int left, right, top, bottom, width = imgA.getWidth(), height = imgA.getHeight();
			left = right = top = bottom = -1;
			
			//===========================FIND THE STAMP============================
	        // Loop over every pixel.;
	        for (int y = 0; y < height; y++) 
	        {
	            for (int x = 0; x < width; x++) 
	            {
	                // Compare the pixels for equality.
					Color cA = new Color(imgA.getRGB(x, y));
					Color cB = new Color(imgB.getRGB(x, y));
					int diffBlue=Math.abs(cA.getBlue()-cB.getBlue());
					int diffRed=Math.abs(cA.getRed()-cB.getRed());
					int diffGreen=Math.abs(cA.getGreen()-cB.getGreen());
					if(diffBlue>10 || diffRed>10 || diffGreen>10)	                	
	                {
	                    if(left == -1)
	                    {
	                    	left = x;
	                    }
	                    else
	                    {
	                    	if(left>x)
	                    	{
	                    		left = x;
	                    	}
	                    }
	                    if(right == -1)
	                    {
	                    	right = x;
	                    }
	                    else
	                    {
	                    	if(right<x)
	                    	{
	                    		right = x;
	                    	}
	                    }
	                    if(top == -1)
	                    {
	                    	top = y;
	                    }
	                    else
	                    {
	                    	if(top>y)
	                    	{
	                    		top = y;
	                    	}
	                    }
	                    if(bottom == -1)
	                    {
	                    	bottom = y;
	                    }
	                    else
	                    {
	                    	if(bottom<y)
	                    	{
	                    		bottom = y;
	                    	}
	                    }
	                }
	            }
	        }

	        //=====================================BUILD THE RECTANGLE==============================
	        //Draw lines of rectangle
	        if(left == -1)
	        {
	        	logger.error("The two screenshots are the same");
	        	//JOptionPane.showMessageDialog(null, "The two screenshots are the same", "Error : screenshot", JOptionPane.WARNING_MESSAGE);
	        	left = right = top = bottom = 0;
	        }
			logger.info("rectangle : left :" + left + " | top : " + top + " | right : " + right + " | bottom : " + bottom);
	        for(int i = left; i < right; i++)
	        {
	        	imgB.setRGB(i, bottom, 0x1fffffff);
	        	imgB.setRGB(i, top, 0xffff1fff);
	        }
	        //Draw Columns of rectangle
	        for(int i = top; i < bottom; i++)
	        {
	        	imgB.setRGB(left, i, 0x1fffffff);
	        	imgB.setRGB(right, i, 0xffff1fff);
	        }
	        
	        //====================================SAVE THE LOG IMAGE===============================
	        try 
	        {
	    		logger.info("Saving pictures");
	            ImageIO.write(imgB, "jpg", new File(ServiceConfig.image.getPath() + "\\" + save.getName()+"_(imgB).jpg"));  // ignore returned boolean
	            ImageIO.write(imgA, "jpg", new File(ServiceConfig.image.getPath() + "\\" + save.getName()+"_(imgA).jpg"));  // ignore returned boolean
	        } catch(IOException e) 
	        {
	        	throw new ErrorException("06 : "+e.getMessage(), 1);
	        }
	        if(left == -1)
	        {
	        	throw new ErrorException("09 : The two screenshots are the same", 1, new File(ServiceConfig.image.getPath() + "\\" + save.getName()+"_(imgA).jpg"));
	        }
	        return new Rectangle(left-2, top-2, right-left+4, bottom-top+4);
	    }
	    else 
	    {
        	throw new ErrorException("10 : the two screenshot don't have the same format", 1);
	    	//JOptionPane.showMessageDialog(null, "the two screenshot don't have the same format", "Error : screenshot", JOptionPane.WARNING_MESSAGE);
	        //return new Rectangle(0, 0, 0, 0);
	    }
	}
	
	
	/**
	 * Check if the place in parameter is free for a stamp
	 *
	 * @param screen - the image.
	 * @param place - the place to check.
	 * @return true if the place is white
	 */
	public static double isFree(BufferedImage screen, Rectangle place)
	{
		int cpt = 0;
		int x = (int)place.getMinX();
		while(x < (int)place.getMaxX())
		{
			int y = (int)place.getMinY();
			while(y < (int)place.getMaxY())
			{
				Color c = new Color(screen.getRGB(x, y));
				if(c.getBlue()>200 && c.getRed()>200 && c.getGreen()>200)cpt++;
				y++;
			}
			x++;
		}
		//logger.info(cpt/(place.getWidth()*place.getHeight()));
		return cpt/(place.getWidth()*place.getHeight());
	}

	/**
	 * set the value of stop
	 * @param stop
	 */
	public static Rectangle dimension(BufferedImage whitepage)
	{
		logger.info("getting dimensions");
		int xmid = whitepage.getWidth()/2, ymid = whitepage.getHeight()/2;
		int x1 = xmid, y1 = ymid, x2 = xmid, y2 = ymid;
		Boolean found = false;
		while(x1 > 0 && !found)
		{
			int pixel =whitepage.getRGB(x1, ymid);
		    int red = (pixel >> 16) & 0xff;
		    int green = (pixel >> 8) & 0xff;
		    int blue = (pixel) & 0xff;
			if(red == 255 && green == 255 && blue == 255)
			{
				x1--;
			}
			else
			{
				found = true;
			}
		}
		int pixelGrey =whitepage.getRGB(x1, ymid);
		found = false;
		while(x1 > 0 && !found)
		{
			int pixel =whitepage.getRGB(x1, ymid);
			if(pixel==pixelGrey)
			{
				x1--;
			}
			else
			{
				found = true;
				x1++;
			}
		}

		
		
		found = false;
		while(y1 > 0 && !found)
		{
			int pixel =whitepage.getRGB(xmid, y1);
		    int red = (pixel >> 16) & 0xff;
		    int green = (pixel >> 8) & 0xff;
		    int blue = (pixel) & 0xff;
			if(red == 255 && green == 255 && blue == 255)
			{
				y1--;
			}
			else
			{
				found = true;
			}
		}
		pixelGrey =whitepage.getRGB(xmid, y1);
		found = false;
		while(y1 > 0 && !found)
		{
			int pixel =whitepage.getRGB(xmid, y1);
			if(pixel==pixelGrey)
			{
				y1--;
			}
			else
			{
				found = true;
				y1++;
			}
		}


		
		
		found = false;
		while(x2 < whitepage.getWidth() && !found)
		{
			int pixel =whitepage.getRGB(x2, ymid);
		    int red = (pixel >> 16) & 0xff;
		    int green = (pixel >> 8) & 0xff;
		    int blue = (pixel) & 0xff;
			if(red == 255 && green == 255 && blue == 255)
			{
				x2++;
			}
			else
			{
				found = true;
			}
		}
		found = false;
		pixelGrey =whitepage.getRGB(x2, ymid);
		while(x2 < whitepage.getWidth() && !found)
		{
			int pixel =whitepage.getRGB(x2, ymid);
			if(pixel == pixelGrey)
			{
				x2++;
			}
			else
			{
				found = true;
				x2--;
			}
		}
		
		found = false;
		while(y2 < whitepage.getHeight() && !found)
		{
			int pixel =whitepage.getRGB(xmid, y2);
		    int red = (pixel >> 16) & 0xff;
		    int green = (pixel >> 8) & 0xff;
		    int blue = (pixel) & 0xff;
			if(red == 255 && green == 255 && blue == 255)
			{
				y2++;
			}
			else
			{
				found = true;
			}
		}
		found = false;
		pixelGrey =whitepage.getRGB(xmid, y2);
		while(y2 < whitepage.getHeight() && !found)
		{
			int pixel =whitepage.getRGB(xmid, y2);
			if(pixel == pixelGrey)
			{
				y2++;
			}
			else
			{
				found = true;
				y2--;
			}
		}
		logger.info("dimensions : left : " + x1 + " | right : " + x2 + " | top : " + y1 + " | bottom : " + y2);
		return new Rectangle(x1,y1,x2-x1,y2-y1);
	}
	
	/**
	 * 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);
		}
	}
}
