/**
This plugin, written by Jon Harmon, implements the File/Open Next command.
It opens the "next" image in a directory, where "next" can be the
succeeding or preceeding image in the directory list.
Press shift-o to open the succeeding image or 
alt-shift-o to open the preceeding image.
It can leave the previous file open, or close it.
You may contact the author at Jonathan_Harman at yahoo.com
This code was modified from Image_Browser by Albert Cardona
*/

package ij.plugin;
import ij.*;
import ij.io.*;
import ij.gui.*;
import java.io.File;

public class NextImageOpener implements PlugIn {

	boolean forward = true; // default browse direction is forward
	boolean closeCurrent = true; //default behavior is to close current window
	ImagePlus imp0;
	
	public void run(String arg) {
		/* get changes to defaults */
		if (arg.equals("backward") || IJ.altKeyDown()) forward = false;
		if (arg.equals("backwardsc")) {
			forward = false;
			closeCurrent = false;
		}
		if (arg.equals("forwardsc")) {
			forward = true;
			closeCurrent = false;
		}
				
		// get current image; displays error and aborts if no image is open
 		imp0 = IJ.getImage();
 		// get current image directory
 		String currentPath = getDirectory(imp0);
		if (IJ.debugMode) IJ.log("OpenNext.currentPath:" + currentPath);
		if (currentPath==null) {
			IJ.error("Next Image", "Directory information for \""+imp0.getTitle()+"\" not found.");
			return;
		}
		String nextPath = getNext(currentPath, getName(imp0), forward);
		if (IJ.debugMode) IJ.log("OpenNext.nextPath:" + nextPath);
		// open
		if (nextPath != null) {
			String rtn = open(nextPath);
			if (rtn==null)
				open(getNext(currentPath, (new File(nextPath)).getName(), forward));
		}
	}
	
	String getDirectory(ImagePlus imp) {
		FileInfo fi = imp.getOriginalFileInfo();
		if (fi==null) return null;
		String dir = fi.openNextDir;
		if (dir==null) dir = fi.directory;
		return dir;
	}

	String getName(ImagePlus imp) {
		String name = imp.getTitle();
		FileInfo fi = imp.getOriginalFileInfo();
		if (fi!=null) {
			if (fi.openNextName!=null)
				name = fi.openNextName;
			else if (fi.fileName!=null)
				name = fi.fileName;
		}
		return name;
	}
	
	String open(String nextPath) {
		int nImages = WindowManager.getImageCount();
		ImagePlus imp2 = IJ.openImage(nextPath);		
		if (imp2==null) {
			if (WindowManager.getImageCount()>nImages)
				return "ok";
			else
				return null;
		}
		String newTitle = imp2.getTitle();
		if (imp0.changes) {
			String msg;
			String name = imp0.getTitle();
			if (name.length()>22)
				msg = "Save changes to\n" + "\"" + name + "\"?";
			else
				msg = "Save changes to \"" + name + "\"?";
			YesNoCancelDialog d = new YesNoCancelDialog(imp0.getWindow(), "ImageJ", msg);
			if (d.cancelPressed())
				return "Canceled";
			else if (d.yesPressed()) {
				FileSaver fs = new FileSaver(imp0);
				if (!fs.save())
					return "Canceled";
			}
			imp0.changes = false;
		}
		if (!(imp0 instanceof CompositeImage) && (imp2.isComposite() || imp2.isHyperStack())) {
			// imp0.setImage(imp2) does not work if 'imp2' is composite and 'imp0' is not
			imp2.show();
			imp0.close();
			imp0 = imp2;
		} else
			imp0.setImage(imp2);
		return "ok";
	}
	
	/** gets the next image name in a directory list */
	String getNext(String path, String imageName, boolean forward) {
		File dir = new File(path);
		if (!dir.isDirectory())
			return null;
		String[] names = dir.list();
		if (names==null) {
			IJ.log("getNext directory empty: "+path);
			return null;
		}
		ij.util.StringSorter.sort(names);
		int thisfile = -1;
		for (int i=0; i<names.length; i++) {
			if (names[i].equals(imageName)) {
				thisfile = i;
				break;
			}
		}
		if (IJ.debugMode) IJ.log("OpenNext.thisfile:" + thisfile);
		if(thisfile == -1) return null;// can't find current image
		
		// make candidate the index of the next file
		int candidate = thisfile + 1;
		if (!forward) candidate = thisfile - 1;
		if (candidate<0) candidate = names.length - 1;
		if (candidate==names.length) candidate = 0;
		// keep on going until an image file is found or we get back to beginning
		while (candidate!=thisfile) {
			String nextPath = path + names[candidate];
			if (IJ.debugMode) IJ.log("OpenNext: "+ candidate + "  " + names[candidate]);
			File nextFile = new File(nextPath);
			boolean canOpen = true;
			if (names[candidate].startsWith(".") || nextFile.isDirectory())
				canOpen = false;
			if (canOpen) {
				Opener o = new Opener();
				int type = o.getFileType(nextPath);
				if (type==Opener.JAVA_OR_TEXT
				||  type==Opener.ROI ||  type==Opener.TEXT)
					canOpen = false;
			}
			if (canOpen)
					return nextPath;
			else {// increment again
				if (forward)
					candidate = candidate + 1;
				else
					candidate = candidate - 1;
				if (candidate<0) candidate = names.length - 1;
				if (candidate == names.length) candidate = 0;
			}
			
		}
		if (IJ.debugMode) IJ.log("OpenNext: Search failed");
		return null;
	}

}
