/**
 * 
 */
package org.richfaces.realworld.util;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;

import org.richfaces.model.UploadItem;
import org.richfaces.realworld.service.Constants;

/**
 * @author Andrey Markavtsov
 * 
 */
public class ImageUtils {
	
	public static class ImageDimension {
		public int WIDTH;
		public int HEIGHT;
		public String POSTFIX_NAME;
		public ImageDimension(int width, int height, String postfix_name) {
			super();
			WIDTH = width;
			HEIGHT = height;
			POSTFIX_NAME = postfix_name;
		}
	};
	
	public static final String _MEDIUM = "_medium";
	public static final String _MINI = "_mini";

	
	public static ImageDimension MINI = new ImageDimension(100, 100, _MINI); 
	public static ImageDimension MEDIUM = new ImageDimension(640, 480, _MEDIUM);
	

	BufferedImage bufferedImage;

	double width;
	double height;

	public ImageUtils(BufferedImage bufferedImage) {
		if (bufferedImage == null) {
			throw new NullPointerException("Buffered image is null");
		}

		this.height = bufferedImage.getHeight();
		this.width = bufferedImage.getWidth();
		this.bufferedImage = bufferedImage;
	}

	private BufferedImage scaleToWidth(int width) throws IOException {
		double height = width * this.height / this.width;
		BufferedImage newImage = new BufferedImage(width, (int) height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D graphics2D = createGraphics(newImage);
		graphics2D.drawImage(bufferedImage, 0, 0, (int) width, (int) height,
				null);
		return newImage;
	}

	private BufferedImage scaleToHeight(int height) throws IOException {
		double width = height * this.width / this.height;
		BufferedImage newImage = new BufferedImage((int) width, (int) height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D graphics2D = createGraphics(newImage);
		graphics2D.drawImage(bufferedImage, 0, 0, (int) width, (int) height,
				null);
		return newImage;
	}

	private Graphics2D createGraphics(BufferedImage image) {
		Graphics2D graphics2D = image.createGraphics();
		graphics2D.setBackground(new Color(255, 255, 255));
		graphics2D.clearRect(0, 0, image.getWidth(), image.getHeight());
		graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BICUBIC);
		return graphics2D;
	}

	public BufferedImage resizeImage(double width, double height)
			throws IOException {

		if (width > height) {
			if (this.bufferedImage.getWidth() < width) {
				return bufferedImage;
			}
			return scaleToWidth((int) width);
		} else {
			if (this.bufferedImage.getHeight() < height) {
				return bufferedImage;
			}
			return scaleToHeight((int) height);
		}

	}

	public static void resizeImage(UploadItem image, String pathToUpload, ImageDimension ... dimensions)
			throws IOException {
		
		BufferedImage bufferedImage = ImageIO.read(new FileImageInputStream(image.getFile()));
		
		ImageUtils utils = new ImageUtils(bufferedImage);
		int width, height;
		
		ImageIO.write(bufferedImage, Constants.JPG, new File(pathToUpload));
		
		for (ImageDimension dimension : dimensions) {
			String fileName =  transformPath(pathToUpload,dimension.POSTFIX_NAME);
			width = dimension.WIDTH;
			height = dimension.HEIGHT;
			BufferedImage resizedBuffer = bufferedImage;
			
			if (width > height) {
				if (bufferedImage.getWidth() > width) {
					resizedBuffer = utils.scaleToWidth((int) width);
				}
			} else {
				if (bufferedImage.getHeight() > height) {
					resizedBuffer = utils.scaleToHeight((int) height);
				}
			}
			
			if (resizedBuffer != null) {
				ImageIO.write(resizedBuffer, Constants.JPG, new File(fileName));
			}
			
		}
		
 	}
	
	public static String transformPath(String target, String substitute){
		String begin = target.substring(0, target.lastIndexOf(Constants.DOT));
		String end = target.substring(target.lastIndexOf(Constants.DOT));
		return begin + substitute + end;
	}

}
