package ijloader;

import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.ImageWindow;
import ij.macro.Interpreter;
import ij.measure.ResultsTable;
import ij.process.ColorProcessor;
import ij.text.TextWindow;

import java.awt.Frame;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.ByteOrder;

import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageInputStreamImpl;

public class IJLoader {

    private static void debugPrint(String msg) {
        System.err.println("[IJLoader] " + msg);
    }
    
    private static class ImageInputStreamWrapper extends ImageInputStreamImpl {
        public ImageInputStreamWrapper(InputStream stream) {
            this.stream = stream;
        }

        @Override
        public int read() throws IOException {
            return stream.read();
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            return stream.read(b, off, len);
        }

        private final InputStream stream;
    }

    public static void main(String args[]) {
        ImageInputStream iStream = new ImageInputStreamWrapper(System.in);

        iStream.setByteOrder(ByteOrder.BIG_ENDIAN);

//        IJ.debugMode = true;
        
        newOut = new PrintStream(new OutputStream() {
            @Override
            public void write(int i) {
                if (i != 13) {
                    savedOut.write(i);
                    outputEmitted = true;
                    savedOut.flush();
                }
            }
        });

        System.setOut(new PrintStream(new OutputStream() {
            @Override
            public void write(int i) {
                System.err.write(i);
            }
        }));

        try {
            int width, height, macroLen, pixBuffer[];
            byte macroBuffer[];
            String macroText;
            while (true) {
                debugPrint("Reading image...");

                newOut.println("BEGIN");

                width = iStream.readInt();
                height = iStream.readInt();

                pixBuffer = new int[width * height];
                iStream.readFully(pixBuffer, 0, pixBuffer.length);

                debugPrint("Image read.");

                ImagePlus imp = new ImagePlus("diamond", new ColorProcessor(
                        width, height, pixBuffer));

                ImageWindow imgWin = new ImageWindow(imp);
                imgWin.setVisible(true);
//                WindowManager.setTempCurrentImage(imp);

                debugPrint("Reading macro...");

                macroLen = iStream.readInt();
                macroBuffer = new byte[macroLen];
                iStream.readFully(macroBuffer);

                macroText = new String(macroBuffer, 0, macroBuffer.length,
                        "ISO8859_1");

                debugPrint("Macro read.");
//                debugPrint(macroText);
                debugPrint("Running macro...");

                outputEmitted = false;
                String macroResult = IJ.runMacro(macroText);
                debugPrint("macroResult: " + macroResult);
                
                debugPrint(" in batch mode: " + Interpreter.isBatchMode());

                debugPrint("** LOG ");
                Frame f[] = WindowManager.getNonImageWindows();
                for (Frame frame : f) {
                    if (frame instanceof TextWindow) {
                        TextWindow tw = (TextWindow) frame;
                        debugPrint(" * " + tw.getTitle());
                        debugPrint(tw.getTextPanel().getText());
                    }
                }
                debugPrint("** END LOG ");

                if (!outputEmitted) {
                    debugPrint("No output received from filter");
                    newOut.println("RESULT");
                    newOut.println(3);
                    newOut.println("0.0");
                }

                debugPrint("Macro executed");

                ResultsTable rTable = ResultsTable.getResultsTable();
                if (rTable != null) {
                    rTable.reset();
                }

                debugPrint("going to close all windows");
                imgWin.close();
//                WindowManager.setTempCurrentImage(null);
                WindowManager.closeAllWindows();
                debugPrint(" done");

                ImagePlus lastImage;
                do {
                    lastImage = Interpreter.getLastBatchModeImage();
                    if (lastImage != null) {
                        Interpreter.removeBatchModeImage(lastImage);
                    }
                } while (lastImage != null);

                debugPrint("Window count: ");
                debugPrint(Integer.toString(WindowManager.getWindowCount()));
                debugPrint("Image count: ");
                debugPrint(Integer.toString(WindowManager.getImageCount()));
            }
        } catch (IOException e) {
            throw new RuntimeException(
                    "Received IO Exception from reading stdin!", e);
        }
    }

    public static void writeDiamondAttribute(String name, String val) {
        debugPrint("writeDiamondAttribute: " + name + " -> " + val);
        newOut.println("ATTR");
        
        newOut.println("K");
        newOut.println(name.length());
        newOut.println(name);

        newOut.println("V");
        newOut.println(val.length());
        newOut.println(val);
    }
    
    public static void writeResult(String val) {
        debugPrint("result: " + val);
        
        newOut.println("RESULT");
        newOut.println(val.length());
        newOut.println(val);
    }
    
    private static PrintStream savedOut = System.out;

    private static PrintStream newOut;

    private static boolean outputEmitted;
}

@@ -26,16 +26,37 @@
  ij.IJ;%0A
+import ij.io.Opener;%0A
 import i
@@ -97,35 +97,8 @@
 er;%0A
-import ij.gui.ImageWindow;%0A
 impo
@@ -158,42 +158,8 @@
 le;%0A
-import ij.process.ColorProcessor;%0A
 impo
@@ -224,104 +224,9 @@
 .io.
-IOException;%0Aimport java.io.InputStream;%0Aimport java.io.OutputStream;%0Aimport java.io.PrintStream
+*
 ;%0Aim
@@ -469,36 +469,32 @@
 %22 + msg);%0A    %7D%0A
-    
 %0A    private sta
@@ -1175,24 +1175,16 @@
 = true;%0A
-        
 %0A       
@@ -1705,44 +1705,24 @@
 int 
-width, height, macroLen, pixBuffer%5B%5D
+imgLen, macroLen
 ;%0A  
@@ -1749,16 +1749,29 @@
 Buffer%5B%5D
+, pixBuffer%5B%5D
 ;%0A      
@@ -1932,57 +1932,14 @@
     
-width = iStream.readInt();%0A                height
+imgLen
  = i
@@ -1993,26 +1993,19 @@
 new 
-int%5Bwidth * height
+byte%5BimgLen
 %5D;%0A 
@@ -2119,293 +2119,252 @@
 );%0A%0A
-                ImagePlus imp = new ImagePlus(%22diamond%22, new ColorProcessor(%0A                        width, height, pixBuffer));%0A%0A                ImageWindow imgWin = new ImageWindow(imp);%0A                imgWin.setVisible(true);%0A//                WindowManager.setTempCurrentImage(imp
+%09%09// save as temp%0A%09%09File tmp = File.createTempFile(%22ijloader%22, %22.img%22);%0A%09%09//%09%09tmp.deleteOnExit();%0A%09%09FileOutputStream fos = new FileOutputStream(tmp);%0A%09%09fos.write(pixBuffer);%0A%09%09fos.close();%0A%0A%09%09new Opener().open(tmp.getPath());%0A%0A%09%09//%09%09tmp.delete(
 );%0A%0A
@@ -4046,40 +4046,8 @@
 %22);%0A
-                imgWin.close();%0A
 //  

Change IJLoader to read compressed image directly from Diamond