package ludumdare.game;

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.Toolkit;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.PixelGrabber;
import java.awt.image.RGBImageFilter;

import javax.swing.ImageIcon;

public class ImageManager {
	
	// This method returns true if the specified image has transparent pixels
	public static boolean hasAlpha(Image image) {
		// If buffered image, the color model is readily available
		if (image instanceof BufferedImage) {
			BufferedImage bimage = (BufferedImage)image;
			return bimage.getColorModel().hasAlpha();
		}

		// Use a pixel grabber to retrieve the image's color model;
		// grabbing a single pixel is usually sufficient
		PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
		try {
			pg.grabPixels();
		} catch (InterruptedException e) {
		}

		// Get the image's color model
		ColorModel cm = pg.getColorModel();
		return cm.hasAlpha();
	}

	public static BufferedImage toBufferedImage(Image image) { 
		if (image instanceof BufferedImage) { 
			return (BufferedImage)image; 
		} 
		// This code ensures that all the pixels in the image are loaded 
		image = new ImageIcon(image).getImage(); // Determine if the image has transparent pixels; for this method's 
		// implementation, see Determining If an Image Has Transparent Pixels  
		boolean hasAlpha = hasAlpha(image); // Create a buffered image with a format that's compatible with the screen 
		BufferedImage bimage = null; 
		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 
		try { // Determine the type of transparency of the new buffered 
			int transparency = Transparency.OPAQUE; 
			if (hasAlpha) { 
				transparency = Transparency.BITMASK; 
			} // Create the buffered image 
			GraphicsDevice gs = ge.getDefaultScreenDevice(); 
			GraphicsConfiguration gc = gs.getDefaultConfiguration(); 
			bimage = gc.createCompatibleImage( image.getWidth(null), image.getHeight(null), transparency); 
		} catch (HeadlessException e) { // The system does not have a screen 

		} if (bimage == null) { 
			// Create a buffered image using the default color model 
			int type = BufferedImage.TYPE_INT_RGB; 
			if (hasAlpha) { type = BufferedImage.TYPE_INT_ARGB; } 
			bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type); 
		} // Copy image to buffered image 
		Graphics g = bimage.createGraphics(); // Paint the image onto the buffered image 
		g.drawImage(image, 0, 0, null); 
		g.dispose(); 
		return bimage;
	}

	public static BufferedImage makeColorTransparent (BufferedImage im, final Color color) {
		ImageFilter filter = new RGBImageFilter() {
			// the color we are looking for... Alpha bits are set to opaque
			public int markerRGB = color.getRGB() | 0xFF000000;

			public final int filterRGB(int x, int y, int rgb) {
				if ( ( rgb | 0xFF000000 ) == markerRGB ) {
					// Mark the alpha bits as zero - transparent
					return 0x00FFFFFF & rgb;
				}
				else {
					// nothing to do
					return rgb;
				}
			}
		};
		ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
		return toBufferedImage(Toolkit.getDefaultToolkit().createImage(ip));
	}

	public static BufferedImage flipImage(BufferedImage image) {
		AffineTransform tx = AffineTransform.getScaleInstance(-1, 1);
		tx.translate(-image.getWidth(null), 0);
		AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
		return op.filter(image, null);
	}
}
