import java.io.IOException;

public class image {
	public static imagemap inverse(imagemap curPixMap) {
		imagemap pixelMap = curPixMap.copyAll();
		pixelMap.getEveryOne(new pkpix() {
			public void handle(imagemap pixelMap, pixel p, int r, int c) {
				pixelMap.set(r, c, p.invert());
			}
		});
		return pixelMap;
	}
	
	public static imagemap blur(imagemap curPixMap, final int radius) {
		imagemap pixelMap = curPixMap.copyAll();
		pixelMap.getEveryOne(new pkpix() {
			public void handle(imagemap pixelMap, pixel p, int r, int c) {
				pixelMap.set(r, c, pixel.average(pixelMap.get(r, c, c + radius - 1)));
			}
		});
		return pixelMap;
	}
	
	public static imagemap emboss(final imagemap curPixMap) {
		imagemap pixelMap = curPixMap.copyAll();
		pixelMap.getEveryOne(new pkpix() {
			public void handle(imagemap pixelMap, pixel p, int r, int c) {
				if (r == 0 || c == 0) {
					pixelMap.set(r, c, new pixel(128));
					return;
				}
				pixel embossed = p.emboss(curPixMap.get(r-1, c-1));
				pixelMap.set(r, c, embossed);
			}
		});
		return pixelMap;
	}
	
	public static imagemap grayscale(imagemap curPixMap) {
		imagemap pixelMap = curPixMap.copyAll();
		pixelMap.getEveryOne(new pkpix() {
			public void handle(imagemap pixelMap, pixel p, int r, int c) {
				pixelMap.set(r, c, p.grayscale());
			}
		});
		return pixelMap;
	}
	
	public enum Command {
		GRAYSCALE, INVERT, EMBOSS, MOTIONBLUR;
	}

	public static void printUsage() {
		System.out.println("USAGE: java ImageEditor  in-file out-file (grayscale|invert|emboss|motionblur motion-blur-length)");
	}

	public static void main(String[] args) {
		String in, out;
		Command command;
		int	blurRadius = 0;
		try {
			in = args[0];
			out = args[1];
			command = Command.valueOf(args[2].toUpperCase());
			if (command.equals(Command.MOTIONBLUR)) {
				blurRadius = Integer.parseInt(args[3]);
				if (blurRadius <= 0)
					printUsage();
			}
		} catch (Exception e) {
			printUsage();
			return;
		}
		imagemap pixelMap;
		try {
			pixelMap = new imagemap(in);
		} catch (Exception e) {
			printUsage();
			return;
		}
		try {
			switch (command) {
				case GRAYSCALE:
					pixelMap = grayscale(pixelMap);
					break;
				case INVERT:
					pixelMap = inverse(pixelMap);
					break;
				case EMBOSS:
					pixelMap = emboss(pixelMap);
					break;
				case MOTIONBLUR:
					pixelMap = blur(pixelMap, blurRadius);
					break;
				default:
					printUsage();
					return;
			}
		} catch (Exception e) {
			printError("Unexpected error: " + e.getMessage());
			return;
		}
		
		try {
			pixelMap.fileWritter(out);
		} catch (IOException e) {
			printError("Error writing to file '" + out + "'");
			return;
		}
	}
	
	public static void printError(String err) {
		System.out.println(err);
	}
}
