package util;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;

import javax.swing.ImageIcon;

public class ImageProcessor {

	public static Image swapColor(Image image, Color c1, Color c2) {

		int rgb1 = c1.getRGB();
		int rgb2 = c2.getRGB();

		BufferedImage bimage = toBufferedImage(image);

		for(int x = 0; x < bimage.getWidth(); x++)
			for(int y = 0; y < bimage.getHeight(); y++)
				
				if(bimage.getRGB(x, y) == rgb1)
					bimage.setRGB(x, y, rgb2);

		return bimage;
	}

	public static BufferedImage toBufferedImage(Image image) {

		if (image instanceof BufferedImage)
			return (BufferedImage)image;
		
		image = new ImageIcon(image).getImage();
		
		boolean hasAlpha = hasAlpha(image);
		
		BufferedImage bimage = null;

		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

		try {
			
			int transparency = Transparency.OPAQUE;

			if (hasAlpha == true)
				transparency = Transparency.BITMASK;
			
			GraphicsDevice gs = ge.getDefaultScreenDevice();
			GraphicsConfiguration gc = gs.getDefaultConfiguration();

			bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
		}
		
		catch (HeadlessException e)
		{
		}
		
		if (bimage == null) {
			
			int type = BufferedImage.TYPE_INT_RGB;

			if (hasAlpha == true)
				type = BufferedImage.TYPE_INT_ARGB;

			bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
		}
		
		Graphics g = bimage.createGraphics();
		
		g.drawImage(image, 0, 0, null);
		g.dispose();
		
		System.gc();

		return bimage;
	}


	public static boolean hasAlpha(Image image) {
		
		if (image instanceof BufferedImage)
			return ((BufferedImage)image).getColorModel().hasAlpha();
		
		PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
		
		try {
			pg.grabPixels();
		}
		
		catch (InterruptedException e)
		{
		}
		
		return pg.getColorModel().hasAlpha();
	}
	
	public static BufferedImage mixImages(
			BufferedImage backImage, float backAlpha,
			BufferedImage frontImage, float frontAlpha,
			int width, int height) {
		
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		
		backImage = shiftImageAlpha(backImage, -(255 - (int) (backAlpha * (float) 255)));
		frontImage = shiftImageAlpha(frontImage, -(255 - (int) (frontAlpha * (float) 255)));
		
		Graphics g = image.createGraphics();
		
		g.drawImage(backImage, 0, 0, width, height, null);
		g.drawImage(frontImage, 0, 0, width, height, null);
		
		g.dispose();
		
		return image;
	}
	
	public static BufferedImage shiftImageAlpha(BufferedImage image, int alpha) {
		
		BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
		
		for(int x = 0; x < image.getWidth(); x++) {
			for(int y = 0; y < image.getHeight(); y++) {
				
				int rgb = image.getRGB(x, y);
				
				int a = rgb & 0xff000000;
				a = a >>> 24;
				a = shiftAlphaValue(a, alpha);
				
				int r = rgb & 0x00ff0000;
				r = r >>> 16;
		
				int g = rgb & 0x0000ff00;
				g = g >>> 8;
			
				int b = rgb & 0x000000ff;
				
				a = a << 24;
				r = r << 16;
				g = g << 8;
				
				int color = a | r | g | b;
				
				newImage.setRGB(x, y, color);
			}
		}
		
		return newImage;
	}
	
	private static int shiftAlphaValue(int color, int alpha) {
		
		color += alpha;
		
		if(color > 0x000000ff)
			color = 0x000000ff;
		
		if(color < 0x00000000)
			color = 0x00000000;
		
		return color;
	}
}