package cnp.ew.image;

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.io.*;
import cnp.ew.util.*;


public class CpPackedImage
{
    Image packedImage;
    String packedImageName;
    Hashtable fileNameToRectDict;
    Hashtable cachedImages;

    static final int maxPackedImageWidth = 500;

     public static CpPackedImage createPackedImage(Component c, String dirPath)
     {

        int maxHeight = 0;
        int totalWidth = 0;
        int width, height;
        int curX, curY, i;
        Image newImage, curImage;
        String curName;
        Graphics g=null;
        Vector imageNames, images;

        imageNames = getImageNamesInDirectory(dirPath);
        images = getImagesForNames(dirPath, imageNames);

        for (i=0; i < images.size(); i++) {
            curImage = (Image)images.elementAt(i);
            maxHeight = Math.max(curImage.getHeight(c), maxHeight);
            totalWidth += curImage.getWidth(c);
        }

        if (totalWidth > maxPackedImageWidth) {
            width = maxPackedImageWidth;
            // Make sure it rounds up
            height = ((totalWidth + maxPackedImageWidth - 1) / maxPackedImageWidth) * maxHeight;
        } else {
            width = totalWidth;
            height = maxHeight;
        }
        newImage = c.createImage(width, height);
        CpPackedImage packedImage = new CpPackedImage((new File(dirPath)).getName());
        packedImage.setPackedImage(newImage);
        try {
            g = newImage.getGraphics();
            g.setColor(Color.pink);
            g.fillRect(0, 0, width, height);
            curX = 0;
            curY = 0;
            for (i = 0; i < images.size(); i++) {
                curImage = (Image)images.elementAt(i);
                curName = (String)imageNames.elementAt(i);
                if (curX + curImage.getWidth(c) > maxPackedImageWidth) {
                    curY += maxHeight;
                    curX = 0;
                }
                g.drawImage(curImage, curX, curY, c);

                packedImage.registerCroppedImage(curName, new Rectangle(curX, curY, curImage.getWidth(c), curImage.getHeight(c)));
                curX += curImage.getWidth(c);
            }
        } finally {
            if (g != null) {
                g.dispose();
            }
        }

        return packedImage;
     }

     static Vector getImageNamesInDirectory(String dirPath)
     {
        File dir = new File(dirPath);
        Vector imageNames = new Vector();

        if (!dir.isDirectory()) {
            throw new IllegalArgumentException("Directory does not exist " + dirPath);
        }

        String [] allFileNames = dir.list();

        for (int i=0; i < allFileNames.length; i++) {
            if (allFileNames[i].endsWith(".gif")) {
                imageNames.addElement(allFileNames[i]);
            }
        }

        return imageNames;
    }

    static Vector getImagesForNames(String directoryName, Vector imageNames)
    {
        Image image;
        String name;
        Vector images = new Vector(imageNames.size());
        MediaTracker tracker = new MediaTracker(CpToolkit.defaultComponent());

        for (int i=0; i < imageNames.size(); i++) {
            name = (String)imageNames.elementAt(i);
            image = Toolkit.getDefaultToolkit().getImage(directoryName + "\\" + name);
            images.addElement(image);
            tracker.addImage(image, i);
        }
        try {
            tracker.waitForAll();
        } catch (InterruptedException e) {
        }
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
        return images;
    }


    public CpPackedImage(String imageName)
    {
        CpToolkit.registerImageName(imageName);
        packedImageName = imageName;
        fileNameToRectDict = new Hashtable();
        cachedImages = new Hashtable();
    }

    void setPackedImage(Image image)
    {
        packedImage = image;
    }

    public Image getPackedImage()
    {
        return packedImage;
    }

    public void registerCroppedImage(String imageName, Rectangle rect)
    {
        fileNameToRectDict.put(imageName, rect);
    }

    /**
     * packedImageName - name without the .gif ending
     */
    public void genCode(PrintStream stream)
    {
        String imageName;
        Rectangle rect;

        stream.println("    static void registerPackedImageFor" + CpTextManipulator.capitalize(packedImageName) + "Images()");
        stream.println("    {");
        stream.println("        CpPackedImage packedImage = new CpPackedImage(\"" + packedImageName + ".gif\");");
        Enumeration imageNames = fileNameToRectDict.keys();
        while (imageNames.hasMoreElements()) {
            imageName = (String)imageNames.nextElement();
            rect = (Rectangle)fileNameToRectDict.get(imageName);
            stream.println("        packedImage.registerCroppedImage(\"" + imageName + "\", new Rectangle(" + rect.x + ", " + rect.y + ", " + rect.width + ", " + rect.height + "));");
        }
        stream.println();
        stream.println("        CpImageGetter.getDefault().addPackedImage(packedImage);");
        stream.println("    }");
    }

    public boolean isImageInPackedImage(String imageName)
    {
        return fileNameToRectDict.get(imageName) != null;
    }


    public Image getImage(String imageName)
    {
        Rectangle rect = (Rectangle)fileNameToRectDict.get(imageName);

        if (rect == null) {
            return null;
        }

        Image cachedImage = (Image)cachedImages.get(imageName);
        if (cachedImage != null) {
//System.out.println("found cached image " + imageName);
            return cachedImage;
        }

        Component component = CpToolkit.defaultComponent();

        if (packedImage == null) {
            packedImage = CpToolkit.getImage(packedImageName, false);
        }



//System.out.println("found image " + imageName + " in packedImage, adding to cache");
        int pixels[] = new int[rect.width*rect.height];
        PixelGrabber grabber = new PixelGrabber(
                packedImage, rect.x, rect.y, rect.width, rect.height, pixels, 0, rect.width );
        try { grabber.grabPixels(); } catch (Exception e) {}
        MemoryImageSource mem = new MemoryImageSource(rect.width, rect.height, pixels, 0, rect.width);

        cachedImage = component.createImage(mem);
        cachedImages.put(imageName, cachedImage);
        return cachedImage;

    }
}

