import java.util.*;

public class ImageTool {
    static String version = " 12 June 2005";

    static ReducedData image;

    public static void main(String args[]) {
	versionInfo();

	if(args.length == 0) usage();
	else if(args[0].equalsIgnoreCase("-help")) usage();

	try {	    
	    image = new ReducedData(args[args.length-1]);
	    
	    for(int i=0; i<args.length-1; i++) option(args[i]);
	     
	    image.write();
	}
	catch(Exception e) { e.printStackTrace(); }
    }

    public static boolean option(String optionString) {
	StringTokenizer tokens = new StringTokenizer(optionString, "=,");

	String key = tokens.nextToken();

	if(key.equalsIgnoreCase("-clip")) {
	    image.clip(Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND,
		       Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND,
		       Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND, 
		       Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND);
	}
	else if(key.equalsIgnoreCase("-out")) {
	    image.fileName = tokens.nextToken();
	}
	else if(key.equalsIgnoreCase("-pick")) {
	    try { image.writeImage(tokens.nextToken()); }
	    catch(Exception e) { e.printStackTrace(); }
	    System.exit(0);
	}
	else if(key.equalsIgnoreCase("-name")) {
	    image.fileName = Crush.workPath + tokens.nextToken();
	}
	else if(key.equalsIgnoreCase("-correct")) {
	    String value = tokens.nextToken();
	    if(value.equalsIgnoreCase("point")) image.correctFluxesFor(image.beamFWHM);
	    else if(value.equalsIgnoreCase("none")) image.correctFluxesFor(Double.NaN);
	    else image.correctFluxesFor(Double.parseDouble(value) * Unit.ArcSECOND);
	}	
	else if(key.equalsIgnoreCase("-regrid")) {
	    image.regrid(Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND);
	}
	else if(key.equalsIgnoreCase("-convolve")) {
	    image.convolve(Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND);
	}
	else if(key.equalsIgnoreCase("-smooth")) {
	    image.convolveTo(Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND);
	}
	else if(key.equalsIgnoreCase("-extFilter")) {
	    image.filterAbove(Double.parseDouble(tokens.nextToken()) * Unit.ArcSECOND);
	}
	else if(key.equalsIgnoreCase("-deconvolve")) {
	    double[][] beam = null;
	    double replacementFWHM = 4.0 * Unit.ArcSECOND;
	    StringTokenizer specs = new StringTokenizer(tokens.nextToken(), ":");
	    String beamSpec = specs.nextToken(); 

	    try { beam = image.getBeam(Double.parseDouble(beamSpec) * Unit.ArcSECOND); }

	    catch(NumberFormatException e)  {
		try {
		    ReducedData beamImage = new ReducedData(beamSpec);
		    beam = beamImage.clean;
		}
		catch(Exception e2) { System.err.println("ERROR! Cannot open beam FITS file " + beamSpec); }		
	    }		
	    
	    if(specs.hasMoreTokens()) replacementFWHM = Double.parseDouble(specs.nextToken()) * Unit.ArcSECOND;
	    
	    if(beam != null) image.clean(beam, 0.1, replacementFWHM);
	}
	else if(key.equalsIgnoreCase("-minexp")) {
	    clipExp(Double.parseDouble(tokens.nextToken()));
	}
	else if(key.equalsIgnoreCase("-rmsclip")) {
	    clipRMS(Double.parseDouble(tokens.nextToken()));
	}
	else if(key.equalsIgnoreCase("-rmsscale")) {
	    image.rmsScale(Double.parseDouble(tokens.nextToken()));
	}
	else if(key.equalsIgnoreCase("-scale")) {
	    image.scale(Double.parseDouble(tokens.nextToken()));
	}
	else if(key.equalsIgnoreCase("-offset")) {
	    image.math('+', Double.parseDouble(tokens.nextToken()) * image.fitsUnit.value);
	}
	else if(key.equalsIgnoreCase("-unit")) {
	    image.setUnit(tokens.nextToken());
	}
	else if(key.equalsIgnoreCase("-help")) usage();
	else return false;

	return true;
    
    }

    public static void clipExp(double level) {
	double minCount = level * image.getMax(image.count);
	for(int i=0; i<image.sizeX; i++) for(int j=0; j<image.sizeY; j++) if(image.flag[i][j] == 0) 
	    if(image.count[i][j] < minCount) image.flag[i][j] = 1;
    }

    public static void clipRMS(double level) {
	for(int i=0; i<image.sizeX; i++) for(int j=0; j<image.sizeY; j++)
	    if(Math.abs(image.rms[i][j]) > level) image.flag[i][j] = 1;
    }

    public static void versionInfo() {
	System.out.println("imagetool -- Image Manipulation Utility for SHARC2 maps.");
	System.out.println("             Author: Attila Kovacs <attila@submm.caltech.edu>");
	System.out.println("             Version: " + version);
	System.out.println();
    }

    public static void usage() {
	System.out.println("usage: imagetool [options] <filename>");
	System.out.println();
	System.out.println("options:");
	System.out.println();

	optionsSummary();

	System.out.println();	
	System.exit(0);
    }
	
    public static void optionsSummary() {
	System.out.println("    -help         Provides this help screen.");
	System.out.println("    -out=         Specify the output file name. Default overwrites input.");
	System.out.println("    -pick=        Write single image (flux|s2n|rms|time).");
	System.out.println("    -name=        Specify the output file name relative to output path.");
	System.out.println("    -clip=        Followed by 4 comma separated floats defining the clipping");
	System.out.println("                  corners as RA,DEC offsets.");
	System.out.println("    -regrid=      Regrid image to the specified grid size (arcsec).");
	System.out.println("    -correct=     Apply flux corrections to the specified FWHM source(s).");
	System.out.println("    -convolve=    Convolve with the specified FWHM beam size. ");
	System.out.println("    -smooth=      Smooth map to the specified FWHM beam size. ");
	System.out.println("    -extFilter=   Filter extended structures above the specified scale. ");
	System.out.println("    -deconvolve=  Deconvolve image. Argument is either:");
	System.out.println("                     BeamFWHM[:replacmentFWHM]");
	System.out.println("                     <BeamFITSFile>[:replacmentFWHM]");
	System.out.println("    -minExp=      Realtive Exposure under which to clip map.");
	System.out.println("    -rmsClip=     Specify a noise level above which to clip displayed map.");
	System.out.println("    -rmsScale=    Scale the map noise with the specified factor.");
	System.out.println("    -scale=       Scale the map and noise with the specified factor.");
	System.out.println("    -offset=      Add a specified offset, in FITS units (see -unit=) to map.");
	System.out.println("    -Jy=          Specify the voltage response for a 1 Jy source..");	
	System.out.println("    -unit=        Specify the output map unit.");
    }
}
		
	
