/*
 * @(#)ImageIOView.java  1.0.1  2011-08-15
 *
 * Copyright (c) 2004 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.view;

import org.monte.media.mpo.MPOImageReader;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import javax.activation.*;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import org.jhotdraw.gui.Worker;
import org.jhotdraw.util.Images;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * View for Image files supported by the javax.imageio API of Java 1.4 and higher.
 *
 * @author  Werner Randelshofer
 * @version 1.0.1 2011-08-15 Removes unused code. 
 * <br>1.0  June 11, 2004  Created.
 */
public class ImageIOView extends ImageView {

    /** The file being viewed. Null if unknown. */
    private File file;

    /** Creates new form. */
    public ImageIOView() {
        initComponents();
    }

    @Override
    public void setCommandContext(String verb, final DataHandler dh)
            throws IOException {
        dispose();
        if (dh != null) {
            final DataSource source = dh.getDataSource();
            final ArrayList<ImageListItem> list = new ArrayList<ImageListItem>();
            ImageInputStream in = null;
            try {
                if (source instanceof FileDataSource) {
                    file = ((FileDataSource) source).getFile();
                    boolean isTGA = file.getName().toLowerCase().endsWith(".tga");
                    if (isTGA) {
                        in = new MemoryCacheImageInputStream(new BufferedInputStream(new FileInputStream(file)));
                    } else {
                        in = new FileImageInputStream(file);
                    }
                } else {
                    in = new MemoryCacheImageInputStream(new BufferedInputStream(source.getInputStream()));
                }
                LinkedList<ImageReader> readers = new LinkedList<ImageReader>();
                for (Iterator<ImageReader> iter = ImageIO.getImageReaders(in); iter.hasNext();) {
                    ImageReader ir = iter.next();
                    
                    // try with MPOImageReader first
                    if (ir instanceof MPOImageReader) {
                        readers.addFirst(ir);
                    } else {
                        readers.addLast(ir);
                    }
                }

                for (ImageReader r : readers) {
                    // Try out the reader
                    // ------------------
                    try {
                        in.seek(0);
                        r.setInput(in);
                        IIOMetadata streamMetadata = r.getStreamMetadata();
                        if (streamMetadata != null) {
                            parseMetadata(streamMetadata, System.out);
                        }
                        for (int i = 0; true; i++) {
                            IIOMetadata imageMetadata = r.getImageMetadata(i);
                            if (imageMetadata != null) {
                                parseMetadata(imageMetadata, System.out);
                            }
                            BufferedImage img = r.read(i);
                            list.add(new ImageListItem(img, null));
                        }

                    } catch (Throwable e) {
                        // if we haven't read anything yet, try with next reader
                        
                          //     e.printStackTrace();
                        if (list.size() > 0) {
                            break;
                        }
                    }

                    r.dispose();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            if (list.size() > 1) {
                imageList.setFixedCellWidth(128);
                imageList.setPreferredSize(new Dimension(128, 128));
                listScrollPane.setVisible(true);
                revalidate();
            }

            if (list.size() > 0) {
                imagePanel.setImage(list.get(0).getImage());
            }

            if (list.size() > 1) {
                new Worker() {

                    @Override
                    protected Object construct() throws Exception {
                        for (int i = 0; i < list.size(); i++) {
                            final ImageListItem ili = list.get(i);

                            ili.setThumbnail(new ImageIcon(Images.getScaledInstance(ili.getImage(), 128, -1)));
                            SwingUtilities.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    DefaultListModel dlm = ((DefaultListModel) imageList.getModel());
                                    dlm.addElement(ili);
                                }
                            });
                        }
                        return null;
                    }
                }.start();
            }
        }
        // }
    }

    @Override
    public String getViewName() {
        return "Javax Image IO View";
    }


    private void parseMetadata(IIOMetadata m, PrintStream out) {
        if (true) {
            return;
        }
        String[] formatNames = m.getMetadataFormatNames();
        if (formatNames != null) {
            for (String fName : formatNames) {
                out.println("Metadata format name:" + fName);
                Node node = m.getAsTree(fName);
                parseMetadata(node, "", out);
            }
        }

    }

    private void parseMetadata(Node n, String indent, PrintStream out) {
        out.print(indent + "<" + n.getNodeName());

        NamedNodeMap attr = n.getAttributes();
        for (int i = 0; i < attr.getLength(); i++) {
            Node a = attr.item(i);
            out.print(" " + a.getNodeName() + (a.getNodeValue() == null ? "" : "=\"" + a.getNodeValue()) + "\"");
        }
        if (n.getNodeValue() != null || n.getChildNodes().getLength() > 0) {
            out.println(">");
            if (n.getNodeValue() != null) {
                out.print(n.getNodeValue());
            }
            NodeList children = n.getChildNodes();
            String subIndent = indent + " ";
            for (int i = 0; i < children.getLength(); i++) {
                parseMetadata(children.item(i), subIndent, out);
            }
            out.println(indent + "</" + n.getNodeName() + ">");
        } else {
            out.println("/>");
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents

    }//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
