package ij.plugin;
import ij.*;
import ij.process.*;
import ij.gui.*;
import ij.util.Tools;
import ij.io.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;

/** This plugin implements the File/ /Convert command, 
    which converts the images in a folder to a specified format. */
    public class BatchConverter implements PlugIn, ActionListener {
        private static final String[] formats = {"TIFF", "8-bit TIFF", "JPEG", "GIF", "PNG", "PGM", "BMP", "FITS", "Text Image", "ZIP", "Raw"};
        private static String format = formats[0];
        private static double scale = 1.0;
        private static boolean useBioFormats;
        private static int interpolationMethod = ImageProcessor.BILINEAR;
        private static boolean averageWhenDownSizing;
        private String[] methods = ImageProcessor.getInterpolationMethods();
        private Button input, output;
        private TextField inputDir, outputDir;
        private GenericDialog gd;

    public void run(String arg) {
        if (!showDialog())
            return;
        String inputPath = inputDir.getText();
        if (inputPath.equals("")) {
            IJ.error("Batch Converter", "Please choose an input folder");
            return;
        }
        String outputPath = outputDir.getText();
        if (outputPath.equals("")) {
            IJ.error("Batch Converter", "Please choose an output folder");
            return;
        }
        File f1 = new File(inputPath);
        if (!f1.exists() || !f1.isDirectory()) {
            IJ.error("Batch Converter", "Input does not exist or is not a folder\n \n"+inputPath);
            return;
        }
        File f2 = new File(outputPath);
        if (!outputPath.equals("") && (!f2.exists() || !f2.isDirectory())) {
            IJ.error("Batch Converter", "Output does not exist or is not a folder\n \n"+outputPath);
            return;
        }
        String[] list = (new File(inputPath)).list();
        IJ.resetEscape();
        Opener opener = new Opener();
        opener.setSilentMode(true);
        long t0 = System.currentTimeMillis();
        for (int i=0; i<list.length; i++) {
            if (IJ.escapePressed())
                break;
            if (IJ.debugMode) IJ.log(i+"  "+list[i]);
            String path = inputPath + list[i];
            if ((new File(path)).isDirectory())
                continue;
            if (list[i].startsWith(".")||list[i].endsWith(".avi")||list[i].endsWith(".AVI"))
                continue;
            IJ.showStatus(i+"/"+list.length);
            IJ.showProgress(i+1, list.length);
            ImagePlus imp = null;
            IJ.redirectErrorMessages(true);
            if (useBioFormats)
                imp = Opener.openUsingBioFormats(path);
            else
                imp = opener.openImage(inputPath,list[i]);
            IJ.redirectErrorMessages(false);
            if (imp==null) {
                String reader = useBioFormats?"Bio-Formats not found or":"IJ.openImage()";
                IJ.log(reader+" returned null: "+path);
                continue;
            }
            if (scale!=1.0) {
                int width = (int)(scale*imp.getWidth());
                int height = (int)(scale*imp.getHeight());
                ImageProcessor ip = imp.getProcessor();
                ip.setInterpolationMethod(interpolationMethod);
                ip.setProgressBar(null);
                imp.setProcessor(null, ip.resize(width,height,averageWhenDownSizing));
                ip = null;
            }
            if (format.equals("8-bit TIFF") || format.equals("GIF")) {
                if (imp.getBitDepth()==24)
                    IJ.run(imp, "8-bit Color", "number=256");
                else
                    IJ.run(imp, "8-bit", "");
            }
            IJ.saveAs(imp, format, outputPath+list[i]);
            imp.close();
            imp = null;
        }
        IJ.showStatus(list.length+" files converted in "+IJ.d2s((System.currentTimeMillis()-t0)/1000.0,2)+" seconds");
        IJ.showProgress(1,1);
        Prefs.set("batch.input", inputDir.getText());
        Prefs.set("batch.output", outputDir.getText());
    }
            
    private boolean showDialog() {
        gd = new GenericDialog("Batch Convert");
        addPanels(gd);
        gd.setInsets(15, 0, 5);
        gd.addChoice("Output_format:", formats, format);
        gd.addChoice("Interpolation:", methods, methods[interpolationMethod]);
        //gd.addStringField("Height (pixels): ", height==0?"\u2014":""+height, 6);
        gd.addNumericField("Scale factor:", scale, 2);
        gd.addCheckbox("Average when downsizing", averageWhenDownSizing);
        //gd.addCheckbox("Read images using Bio-Formats", useBioFormats);
        gd.setOKLabel("Convert");
        gd.showDialog();
        if (gd.wasCanceled())
            return false;
        format = gd.getNextChoice();
        interpolationMethod = gd.getNextChoiceIndex();
        //height = (int)Tools.parseDouble(gd.getNextString(), 0.0);
        scale = gd.getNextNumber();
        averageWhenDownSizing = gd.getNextBoolean();
        //useBioFormats = gd.getNextBoolean();
        return true;
    }

    void addPanels(GenericDialog gd) {
        Panel p = new Panel();
        p.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0));
        input = new Button("Input...");
        input.addActionListener(this);
        p.add(input);
        inputDir = new TextField(Prefs.get("batch.input", ""), 45);
        p.add(inputDir);
        gd.addPanel(p);
        p = new Panel();
        p.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 0));
        output = new Button("Output...");
        output.addActionListener(this);
        p.add(output);
        outputDir = new TextField(Prefs.get("batch.output", ""), 45);
        p.add(outputDir);
        gd.addPanel(p);
    }
    
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        String s = source==input?"Input":"Output";
        String path = IJ.getDirectory(s+" Folder");
        if (path==null) return;
        if (source==input)
            inputDir.setText(path);
        else
            outputDir.setText(path);
    }

}