package ij;
import ij.process.*;
import ij.io.*;
import java.awt.image.ColorModel;

/** This class represents an array of disk-resident images. */
public class VirtualStack extends ImageStack {
    private static final int INITIAL_SIZE = 100;
    private String path;
    private int nSlices;
    private String[] names;
    private String[] labels;
    private int bitDepth;
    
    /** Default constructor. */
    public VirtualStack() { }

    /** Creates a new, empty virtual stack. */
    public VirtualStack(int width, int height, ColorModel cm, String path) {
        super(width, height, cm);
        this.path = path;
        names = new String[INITIAL_SIZE];
        labels = new String[INITIAL_SIZE];
        //IJ.log("VirtualStack: "+path);
    }

     /** Adds an image to the end of the stack. */
    public void addSlice(String name) {
        if (name==null) 
            throw new IllegalArgumentException("'name' is null!");
        nSlices++;
       //IJ.log("addSlice: "+nSlices+"  "+name);
       if (nSlices==names.length) {
            String[] tmp = new String[nSlices*2];
            System.arraycopy(names, 0, tmp, 0, nSlices);
            names = tmp;
            tmp = new String[nSlices*2];
            System.arraycopy(labels, 0, tmp, 0, nSlices);
            labels = tmp;
        }
        names[nSlices-1] = name;
    }

   /** Does nothing. */
    public void addSlice(String sliceLabel, Object pixels) {
    }

    /** Does nothing.. */
    public void addSlice(String sliceLabel, ImageProcessor ip) {
    }
    
    /** Does noting. */
    public void addSlice(String sliceLabel, ImageProcessor ip, int n) {
    }

    /** Deletes the specified slice, were 1<=n<=nslices. */
    public void deleteSlice(int n) {
        if (n<1 || n>nSlices)
            throw new IllegalArgumentException("Argument out of range: "+n);
            if (nSlices<1)
                return;
            for (int i=n; i<nSlices; i++)
                names[i-1] = names[i];
            names[nSlices-1] = null;
            nSlices--;
        }
    
    /** Deletes the last slice in the stack. */
    public void deleteLastSlice() {
        if (nSlices>0)
            deleteSlice(nSlices);
    }
       
   /** Returns the pixel array for the specified slice, were 1<=n<=nslices. */
    public Object getPixels(int n) {
        ImageProcessor ip = getProcessor(n);
        if (ip!=null)
            return ip.getPixels();
        else
            return null;
    }       
    
     /** Assigns a pixel array to the specified slice,
        were 1<=n<=nslices. */
    public void setPixels(Object pixels, int n) {
    }

   /** Returns an ImageProcessor for the specified slice,
        were 1<=n<=nslices. Returns null if the stack is empty.
    */
    public ImageProcessor getProcessor(int n) {
        //IJ.log("getProcessor: "+n+"  "+names[n-1]+"  "+bitDepth);
        ImagePlus imp = new Opener().openImage(path, names[n-1]);
        if (imp!=null) {
            int w = imp.getWidth();
            int h = imp.getHeight();
            int type = imp.getType();
            ColorModel cm = imp.getProcessor().getColorModel();
            labels[n-1] = (String)imp.getProperty("Info");
        } else
            return null;
        ImageProcessor ip = imp.getProcessor();
        if (imp.getBitDepth()!=bitDepth) {
            switch (bitDepth) {
                case 8: ip=ip.convertToByte(true); break;
                case 16: ip=ip.convertToShort(true); break;
                case 24:  ip=ip.convertToRGB(); break;
                case 32: ip=ip.convertToFloat(); break;
            }
        }
        if (ip.getWidth()!=getWidth() || ip.getHeight()!=getHeight())
            ip = ip.resize(getWidth(), getHeight());
        return ip;
     }
 
    /** Currently not implemented */
    public int saveChanges(int n) {
        return -1;
    }

     /** Returns the number of slices in this stack. */
    public int getSize() {
        return nSlices;
    }

    /** Returns the label of the Nth image. */
    public String getSliceLabel(int n) {
        String label = labels[n-1];
        if (label==null)
            return names[n-1];
        else if (label.length()<=60)
            return label;
        else
            return names[n-1]+"\n"+label;
    }
    
    /** Returns null. */
    public Object[] getImageArray() {
        return null;
    }

   /** Does nothing. */
    public void setSliceLabel(String label, int n) {
    }

    /** Always return true. */
    public boolean isVirtual() {
        return true;
    }

   /** Does nothing. */
    public void trim() {
    }
    
    /** Returns the path to the directory containing the images. */
    public String getDirectory() {
        return path;
    }
        
    /** Returns the file name of the specified slice, were 1<=n<=nslices. */
    public String getFileName(int n) {
        return names[n-1];
    }
    
    /** Sets the bit depth (8, 16, 24 or 32). */
    public void setBitDepth(int bitDepth) {
        this.bitDepth = bitDepth;
    }

    /** Returns the bit depth (8, 16, 24 or 32), or 0 if the bit depth is not known. */
    public int getBitDepth() {
        return bitDepth;
    }

}