package yi.iu.ui;

import java.awt.*;
import java.beans.*;
import symantec.itools.multimedia.ImageViewer;
import java.awt.image.MemoryImageSource;
import java.util.Vector;
import java.io.*;
import yi.iu.SImage;

/**
 * This class is used to display the internal result of image understanding
 * There are mainly two methods can be used to initialize the display frame
 *   public DisplayFrame(int[] data, int w, int h)
 *   public DisplayFrame(Object displayed, int[] data, int w, int h)
 *
 * The calling class can give itself as the displayed object, so the the frame
 * will add the name of that class in the title. Both methodes need the image
 * data, image width and image height as arguments
 *
 * [Example]
 *   DisplayFrame f= new DisplayFrame(this, rst, d.width, d.height);
 *   f.show();
 *
 * Another useful method are
 *   public void displayInfo(int x, int y),
 *   public void pressInfo(int x, int y),
 *
 * User can override this method to give the different information about the
 * image when user move the moust on the image, and press the mouse button,
 * respectively.
 *
 * Save file funtion can not be used when running in a web browser
 */
public class DisplayFrame extends java.awt.Frame
{
    public int[] imageData;
    public int width,height;

    public DisplayFrame()
    {
        //{{INIT_CONTROLS
        setLayout(null);
        setSize(402,312);
        setVisible(false);
        add(imageViewer);
        imageViewer.setBounds(12,12,378,252);
        infLabel.setAlignment(java.awt.Label.CENTER);
        add(infLabel);
        infLabel.setBounds(84,276,227,23);
        setTitle("Process Result");
        //}}

        //{{REGISTER_LISTENERS
        SymWindow aSymWindow = new SymWindow();
        this.addWindowListener(aSymWindow);
        SymMouseMotion aSymMouseMotion = new SymMouseMotion();
        imageViewer.addMouseMotionListener(aSymMouseMotion);
        SymAction lSymAction = new SymAction();
        SaveAsMenuItem.addActionListener(lSymAction);
        SymMouse aSymMouse = new SymMouse();
        imageViewer.addMouseListener(aSymMouse);
        //}}

        //{{INIT_MENUS
        file.setLabel("File");
        file.add(SaveAsMenuItem);
        SaveAsMenuItem.setLabel("Save As");
        menuBar1.add(file);
        //$$ menuBar1.move(0,360);
        setMenuBar(menuBar1);
        //}}
    }

    // initialize the display frame with the image data and image width & height
    public DisplayFrame(int[] data, int w, int h)
    {
        this();
        imageData= data;
        width=w; height=h;
        Image img = createImage(new MemoryImageSource(w, h, data, 0, w));

        try {
            imageViewer.setStyle(ImageViewer.IMAGE_SCALED_TO_FIT);
            imageViewer.setImage(img);
        }
        catch (PropertyVetoException e) {
            System.err.println("can't set image to viewer!");
        }

        // change the default set of the image viewer
        int dw=0;
        if (w<128) dw=(128-w)/2;
        setSize(w+24+dw*2,h+60);
        imageViewer.setBounds(12+dw,12,w,h);
        infLabel.setBounds(w/2+12-112+dw,h+36,224,24);
    }

    public DisplayFrame(String name, int[] data, int w, int h)
    {
        this(data,w,h);
        setTitle(name);
    }

    public DisplayFrame(String name, int[] data, Dimension d)
    {
        this(name, data,d.width,d.height);
    }

    public DisplayFrame(String name, SImage img)
    {
        this(img.data,img.width,img.height);
        setTitle(name);
    }

    // initialize the display frame with the image data and image width & height
    // also the name of calling class
    public DisplayFrame(Object displayed, int[] data, int w, int h)
    {
        this(data,w,h);
        String st= displayed.getClass().getName();
        setTitle(st);
    }


    public DisplayFrame(String title)
    {
        this();
        setTitle(title);
    }
    public void setVisible(boolean b)
    {
        if(b)
        {
            setLocation(50, 50);
        }
        super.setVisible(b);
    }

/*
    static public void main (String args[])
    {
        (new DisplayFrame()).setVisible(true);
    }
*/

    public void addNotify()
    {
        // Record the size of the window prior to calling parents addNotify.
        Dimension d = getSize();

        super.addNotify();

        if (fComponentsAdjusted)
            return;

        // Adjust components according to the insets
        Insets ins = getInsets();
        setSize(ins.left + ins.right + d.width, ins.top + ins.bottom + d.height);
        Component components[] = getComponents();
        for (int i = 0; i < components.length; i++)
            {
            Point p = components[i].getLocation();
            p.translate(ins.left, ins.top);
            components[i].setLocation(p);
        }
        fComponentsAdjusted = true;
    }

    // Used for addNotify check.
    boolean fComponentsAdjusted = false;

    class SymWindow extends java.awt.event.WindowAdapter
    {
        public void windowClosing(java.awt.event.WindowEvent event)
        {
        Object object = event.getSource();
        if (object == DisplayFrame.this)
            DisplayFrame_WindowClosing(event);
        }
    }

    void DisplayFrame_WindowClosing(java.awt.event.WindowEvent event)
    {
        dispose();		 // dispose of the Frame.
    }
    //{{DECLARE_CONTROLS
    public symantec.itools.multimedia.ImageViewer imageViewer = new symantec.itools.multimedia.ImageViewer();
    public java.awt.Label infLabel = new java.awt.Label();
    //}}

    //{{DECLARE_MENUS
    java.awt.MenuBar menuBar1 = new java.awt.MenuBar();
    java.awt.Menu file = new java.awt.Menu();
    java.awt.MenuItem SaveAsMenuItem = new java.awt.MenuItem();
    //}}


    class SymMouseMotion extends java.awt.event.MouseMotionAdapter
    {
        public void mouseMoved(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == imageViewer)
                imageViewer_mouseMoved(event);
        }
    }

    void imageViewer_mouseMoved(java.awt.event.MouseEvent event)
    {
        // get the mouse position based on the image coordination
        int x= event.getX(),y=event.getY();
        if (x>=width) x=width-1;
        if (y>=height) y=height-1;
        if (x<0) x=0;
        if (y<0) y=0;

        // display the information based on the position of mouse
        displayInfo(x,y);
    }

    // display the information based on the position of pixel at (x,y)
    // this function could be override to display the information wanted
    // the default information just is the RGB color at that point.
    public void displayInfo(int x, int y)
    {
        int rgb= imageData[y*width+x];
        int r=rgb>>16&255,g=rgb>>8&255,b=rgb&255;
        float[] hsi= Color.RGBtoHSB(r, g, b, null);
        int h=(int)(Math.round(hsi[0]*255)),s=(int)(Math.round(hsi[1]*255)),i=(int)(Math.round(hsi[2]*255));
        infLabel.setText("("+x+","+y+"): "+"RGB("+r+","+g+","+b+")"+"HSB("+h+","+s+","+i+")");
    }

    class SymAction implements java.awt.event.ActionListener
    {
        public void actionPerformed(java.awt.event.ActionEvent event)
        {
            Object object = event.getSource();
            if (object == SaveAsMenuItem)
                SaveAsMenuItem_ActionPerformed(event);
        }
    }

    void SaveAsMenuItem_ActionPerformed(java.awt.event.ActionEvent event)
    {
        FileDialog fd= new FileDialog(this, "Save the result", FileDialog.SAVE);
        fd.show();
        String fileName=fd.getDirectory()+fd.getFile();
        if (fileName.endsWith("ppm")) yi.util.io.OutputResult.outputColorImage(fileName, imageData, width, height);
        else if (fileName.endsWith("pgm")) yi.util.io.OutputResult.outputGrayImage(fileName, imageData, width, height);
        else System.err.println("Can't save image format other than ppm and pgm");
        //saveResult(fd.getDirectory()+fd.getFile());
    }

/*
    void saveResult(String file)
    {
        // make data
        byte[] data= new byte[height*width*3];
        for (int i=0;i<height*width;i++) {
            data[i*3]= (byte)(imageData[i]>>16&0xff);
            data[i*3+1]= (byte)(imageData[i]>>8&0xff);
            data[i*3+2]= (byte)(imageData[i]&0xff);
        }

        // write to file
        try {
            DataOutputStream out= new DataOutputStream (
                new FileOutputStream (file));

            out.writeBytes("P6\n"+width+" "+height+"\n"+"255\n");
            out.write(data);
            out.flush();
            out.close();
        }
        catch (Exception e) {
            System.out.println("SaveResult:="+e);
        }

        data=null;
        System.gc();
    }
*/
    class SymMouse extends java.awt.event.MouseAdapter
    {
        public void mouseReleased(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == imageViewer)
                imageViewer_mouseReleased(event);
        }

        public void mouseExited(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == imageViewer)
                imageViewer_mouseExited(event);
        }

        public void mousePressed(java.awt.event.MouseEvent event)
        {
            Object object = event.getSource();
            if (object == imageViewer)
                imageViewer_mousePressed(event);
        }
    }

    int press_x;
    int press_y;
    void imageViewer_mousePressed(java.awt.event.MouseEvent event)
    {
        // get the mouse position based on the image coordination
        int x= event.getX(),y=event.getY();
        if (x>=width) x=width-1;
        if (y>=height) y=height-1;
        if (x<0) x=0;
        if (y<0) y=0;

        press_x=x; press_y=y;
        // display the information based on the position of mouse
        pressInfo(x,y);
    }

    public void pressInfo(int x, int y)
    {
        return;
    }

    public void mouseExit()
    {
        return;
    }


    void imageViewer_mouseExited(java.awt.event.MouseEvent event)
    {
        mouseExit();
    }

    void imageViewer_mouseReleased(java.awt.event.MouseEvent event)
    {
        // get the mouse position based on the image coordination
        int x= event.getX(),y=event.getY();
        if (x>=width) x=width-1;
        if (y>=height) y=height-1;
        if (x<0) x=0;
        if (y<0) y=0;

        if (press_x!=x||press_y!=y)
        // display the information based on the position of mouse
        selectInfo(press_x, press_y,x,y);
    }

    public void selectInfo(int x1, int y1, int x2, int y2)
    {
        return;
    }

    /**
     * Update the image to display
     * @param data
     * @param w
     * @param h
     */
    public void update(int[] data, int w, int h) {
        if (w!=width || h!=height) {
            System.err.println("The dimension of the new image (" + w + "," + h +
                ") is different from the old one (" + width + "," + height + ")");
        }
        Image img = createImage(new MemoryImageSource(w, h, data, 0, w));

        try {
            imageViewer.setStyle(ImageViewer.IMAGE_SCALED_TO_FIT);
            imageViewer.setImage(img);
            imageViewer.repaint();
        }
        catch (PropertyVetoException e) {
            System.err.println("can't set image to viewer!");
        }
    }
}