import java.io.*;
import javax.imageio.*;
import java.awt.image.*;

class LSBSteganographer implements Steganographer {
    private int numChannels;

    LSBSteganographer(int c) {
	numChannels = c;
    }

    public int getNumChannels() {
	return numChannels;
    }

    public void setNumChannels(int c) {
	numChannels = c;
    }

    private Object loadObject(EasyBufferedImage stego) throws IOException {
	for(int i=1; i<8; i++) {
	    try {
		ObjectInputStream fin = new ObjectInputStream(new ImageInputStream(stego, i));
		Object result = fin.readObject();
		return result;
	    } catch(Exception ioe) {
	    }
	}
	throw new IOException("no secret message of type Object in this image");
    }

    private EasyBufferedImage loadImage(EasyBufferedImage stego) throws IOException {
	for(int i=1; i<8; i++) {
	    try {
		return EasyBufferedImage.createImage(ImageIO.read(new ImageInputStream(stego, i)));
	    } catch(Exception ioe) {
	    }
	}

	throw new IOException("no secret message of Image type in this image");
    }


    public Object extract(EasyBufferedImage stego) throws IOException {
	try {
	    return loadObject(stego);
	} catch(IOException ioe) {
	    return loadImage(stego);
	}
    }

    public EasyBufferedImage embed(EasyBufferedImage cover, Object message) throws IOException {
	EasyBufferedImage result = cover.copy();

	if(message instanceof Serializable) {
	    ObjectOutputStream fout = new ObjectOutputStream(new ImageOutputStream(result, getNumChannels()));
	    fout.writeObject(message);
	} else if(message instanceof BufferedImage) {
	    if(!ImageIO.write((BufferedImage)message, "PNG", new ImageOutputStream(result, getNumChannels()))) throw new IOException("embedding failed");
	} else throw new IllegalArgumentException("can't serialize this message");

	return result;
    }
}
