package utility;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.JLabel;

/**
 * 
 * @author TU-Darmstadt BP Gruppe 7 WS17/18
 *	Centralized resource loading methods
 *	for improved performance and easier troubleshooting.
 */
public class ImageImport {
	
	/**
	 * 30x30 pixel FileNotFound Icon, which can be shown without using I/O operations
	 * a red cross.
	 */
	static private BufferedImage defaultImage;
	/*
	 * Save nothing: Reload every image whenever requested.
	 * Save external: Only save images that were found as external file.
	 * Save raw: Save all non-scaled images.
	 * Save everything: self-explanatory.
	 */
	private static final byte SAVE_NOTHING=0, /*SAVE_EXTERNAL=1,*/ SAVE_RAW=2, SAVE_EVERYTHING=4,
								SAVE_MODE=SAVE_EVERYTHING;
	private static HashMap<String, Image> imgStorage;
	private static ImageImport xmp=new ImageImport();//Used to load resources from the JAR.
	
	static{
		/*
		 * creates the default Image 
		 */
		defaultImage = new BufferedImage(30,30,BufferedImage.TYPE_BYTE_INDEXED);
		for(int x = 0; x < 30; x++)
			for(int y = 0; y < 30; y++){
				if(x == 29 || y == 29)
					//Border Bottom/Left -> Light Grey
					(defaultImage).setRGB(x, y, 13158600);
				else if(x == 0 || y == 0)
					//Border Top/Right -> Dark Grey
					(defaultImage).setRGB(x, y, 6316128);
				else if((x == y || x == 31 - y) && 6 < x && x < 25)
					//Red Cross in the middle
					(defaultImage).setRGB(x, y, 13107200);
				else //all other Pixels are white
					(defaultImage).setRGB(x, y, 16777215);
			}
		if(SAVE_MODE!=SAVE_NOTHING)imgStorage=new HashMap<String, Image>();
	}
	
	/**
	 * The rawest function replacing the old method without any default parameters.
	 * Currently not used in HOLEG at all(aside form calls from the convenience methods).
	 * @param url Path to the image to be loaded.
	 * @param w Width the loaded image should be scaled to.
	 * @param h Height the loaded image should be scaled to.
	 * @param hints Hints for the scaling algorithm to be used.
	 * Same as the parameter in the getScaledInstance function of Image.
	 * @return A loaded and scaled image from the requested path.
	 */
	static Image loadImage(String url, int w, int h, int hints){
		if(SAVE_MODE==SAVE_EVERYTHING){
			String key=url+"?"+w+"?"+h+"?"+hints;
			if(imgStorage.containsKey(key))return(imgStorage.get(key));
			else{
				Image img=loadImage(url).getScaledInstance(w, h, hints);
				imgStorage.put(key, img);
				return img;
			}
		}
		return loadImage(url).getScaledInstance(w, h, hints);
	}
	
	/**
	 * Loads an image from the given path and scales it using the smooth algorithm.
	 * @param url Path to the image to be loaded.
	 * @param w Width the loaded image should be scaled to.
	 * @param h Height the loaded image should be scaled to.
	 * @return A loaded and (smoothly) scaled image from the requested path.
	 */
	public static Image loadImage(String url, int w, int h){
		return loadImage(url,w,h, Image.SCALE_SMOOTH);
	}
	
	/**
	 * Loads an image from the given path and scales it using the smooth algorithm.
	 * @param url Path to the image to be loaded.
	 * @param w Width the loaded image should be scaled to.
	 * @param h Height the loaded image should be scaled to.
	 * @return An image loaded from the requested path.
	 */
	public static Image loadImage(String url){
		if(SAVE_MODE!=SAVE_NOTHING){
			if(imgStorage.containsKey(url))return imgStorage.get(url);
			else{
				Image img;
				try {
					img= ImageIO.read(loadStream(url));
				} catch (IOException e) {
					e.printStackTrace();
					return defaultImage;
				}
				imgStorage.put(url, img);
				return img;
			}
		}
		try {
			return ImageIO.read(loadStream(url));
		} catch (IOException e) {
			e.printStackTrace();
			return defaultImage;
		}
	}
	
	/**
	 * Loads any resource with a given path,
	 * regardless of whether it is inside the jar or an external resource.
	 * Every loadImage() function uses this as a basis.
	 * @param url The path (and file name) of the requested resource.
	 * @return An InputStream from the requested resource.
	 */
	public static InputStream loadStream(String url){
		InputStream o=xmp.getClass().getResourceAsStream(url);
		if(o!=null)return o;
		else{
			boolean rootSymbol=false;	//Whether url starts with a / or \
			switch(url.charAt(0)){		//So we can make sure to construct res/path correctly.
			case '/':case '\\':rootSymbol=true;
			}
			try {
				//Mixed separators might cause problems. Will fix later.
				File f=new File(url);//Possible bug with duplicate names.
				if(!f.exists())url="res"+(rootSymbol?"":"/")+url;
				return new FileInputStream(url);
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
			return null;
		}
	}
	
	//Nobody needs an instance of this. I do, because I use it to load images from inside the JAR.
	private ImageImport(){}
}