package ijloader;

import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.io.Opener;
import ij.macro.Interpreter;
import ij.measure.ResultsTable;
import ij.text.TextWindow;

import java.awt.Frame;
import java.io.*;

public class IJLoader {

    final private static IJLoaderOutputStream specialOut = new IJLoaderOutputStream(
            System.out);

    private static class IJLoaderOutputStream extends PrintStream {

        private boolean outputEmitted;

        private boolean resultEmitted;

        public IJLoaderOutputStream(OutputStream out) {
            super(out);
        }

        @Override
        public void write(int i) {
            if (i != 13) {
                super.write(i);
                outputEmitted = true;
                super.flush();
            }
        }

        public void writeResult(String result) {
            if (resultEmitted) {
                throw new IllegalStateException("Result already written");
            }

            resultEmitted = true;

            println("RESULT");
            println(result.length());
            println(result);
        }

        public boolean getOutputEmitted() {
            return outputEmitted;
        }

        public void resetEmitted() {
            outputEmitted = false;
            resultEmitted = false;
        }
    }

    public static void main(String args[]) {
        // err
        System.setOut(new PrintStream(new OutputStream() {
            @Override
            public void write(int i) {
                System.err.write(i);
            }
        }));

        try {
            while (true) {
                innerLoop(System.in, specialOut);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void debugPrint(String msg) {
        System.err.println("[IJLoader] " + msg);
    }

    private static void innerLoop(InputStream in,
            IJLoaderOutputStream specialOut) throws IOException {
        debugPrint("Reading image...");

        specialOut.println("BEGIN");

        DataInputStream iStream = new DataInputStream(in);

        int imgLen = iStream.readInt();

        byte pixBuffer[] = new byte[imgLen];
        iStream.readFully(pixBuffer, 0, pixBuffer.length);

        debugPrint("Image read: " + pixBuffer.length + " bytes");

        // save as temp
        File tmp = File.createTempFile("ijloader", ".img");
        tmp.deleteOnExit();
        FileOutputStream fos = new FileOutputStream(tmp);
        try {
            fos.write(pixBuffer);
        } finally {
            fos.close();
        }

        new Opener().open(tmp.getPath());

        tmp.delete();

        debugPrint("Reading macro...");

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

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

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

        specialOut.resetEmitted();
        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 (!specialOut.getOutputEmitted()) {
            debugPrint("No output received from filter");
            specialOut.writeResult("0.0");
        }

        debugPrint("Macro executed");

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

        debugPrint("going to close all windows");
        // 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()));
    }

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

        specialOut.println("K");
        specialOut.println(name.length());
        specialOut.println(name);

        specialOut.println("V");
        specialOut.println(val.length());
        specialOut.println(val);
    }

    public static void writeResult(String val) {
        debugPrint("result: " + val);
        specialOut.writeResult(val);
    }
}

@@ -2707,32 +2707,37 @@
 t(%22Reading macro
+ name
 ...%22);%0A%0A        
@@ -2880,20 +2880,20 @@
 ng macro
-Text
+Name
  = new S
@@ -2962,16 +2962,34 @@
 8859_1%22)
+.replace('_', ' ')
 ;%0A%0A     
@@ -3009,16 +3009,21 @@
 (%22Macro 
+name 
 read.%22);
@@ -3043,29 +3043,89 @@
 gPrint(macro
-Text)
+Name);%0A%0A        String evalString = %22run(%5C%22%22 + macroName + %22%5C%22);%22
 ;%0A        de
@@ -3149,24 +3149,56 @@
  macro...%22);
+%0A        debugPrint(evalString);
 %0A%0A        sp
@@ -3267,17 +3267,18 @@
 cro(
-macroText
+evalString
 );%0A 

Change around way we run a macro