package charactermanaj.graphics;

import java.awt.image.BufferedImage;
import java.io.IOException;

import charactermanaj.graphics.filters.ColorConvertParameter;
import charactermanaj.graphics.io.ImageCachedLoader;
import charactermanaj.graphics.io.ImageLoader;
import charactermanaj.graphics.io.ImageResource;

public class ColorConvertedImageCachedLoader extends ColorConvertedImageLoaderImpl {

	private ImageCache<ColorConvertedImageKey> caches = new ImageCache<ColorConvertedImageKey>();
	
	public ColorConvertedImageCachedLoader() {
		this(new ImageCachedLoader());
	}
	
	public ColorConvertedImageCachedLoader(ImageLoader imageLoader) {
		super(imageLoader);
	}

	@Override
	public BufferedImage load(ImageResource file,
			ColorConvertParameter colorConvParam) throws IOException {
		if (file == null) {
			throw new IllegalArgumentException();
		}

		ColorConvertParameter param;
		if (colorConvParam == null) {
			param = new ColorConvertParameter();
		} else {
			param = colorConvParam.clone();
		}
		ColorConvertedImageKey key = new ColorConvertedImageKey(param, file);
		
		synchronized (caches) {
			BufferedImage img = caches.get(key);
			if (img == null) {
				img = super.load(file, param);
				caches.set(key, img);
			}
			return img;
		}
	}
	
	public void unlockImages() {
		caches.unlockImages();
	}
	
}

final class ColorConvertedImageKey {
	
	private final ColorConvertParameter colorConvParameter;
	
	private final ImageResource imageResource;
	
	private final long lastModified;
	
	private final int hashCode;
	
	public ColorConvertedImageKey(ColorConvertParameter colorConvParameter, ImageResource imageResource) {
		if (colorConvParameter == null || imageResource == null) {
			throw new IllegalArgumentException();
		}
		this.colorConvParameter = colorConvParameter;
		this.imageResource = imageResource;
		this.lastModified = imageResource.lastModified();
		this.hashCode = imageResource.hashCode()
				^ colorConvParameter.hashCode() ^ (int) this.lastModified;
	}
	
	@Override
	public int hashCode() {
		return this.hashCode;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}
		if (obj != null && obj instanceof ColorConvertedImageKey) {
			ColorConvertedImageKey other = (ColorConvertedImageKey) obj;
			return lastModified == other.lastModified
					&& imageResource.equals(other.imageResource)
					&& colorConvParameter.equals(other.colorConvParameter);
		}
		return false;
	}
}
