package yi.iu.imgdb.desc.gui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import com.borland.jbcl.layout.*;
import symantec.itools.multimedia.*;
import javax.swing.border.*;
import java.util.*;
import java.io.*;
import javax.swing.event.*;
import javax.swing.JFileChooser;

import yi.gui.helper.*;
import yi.iu.imgdb.desc.*;
import yi.util.config.Configuration;

/**
 * ImageDescFrame is the main frame for image description appliation.  It will
 * show a image list list and image description list on the frame.  Other
 * controls include description controls (eg. "open desc..." button), image
 * preview window, and etc.
 *
 * The underlaying description data model is implemented by the class of
 * "ImgDescManager".  ImageDescFrame is responsible for coordinates the
 * functions among those three main components: ImgDescManager (the data model),
 * the image list list, and the image description list.
 *
 * It listens to those three components:
 *
 * It registers itself with ImgDescManager by addFileListListener(this) and
 * addObjListListener(this).
 *
 * It registers itself with imgList (image list list) by
 * addListSelectionListener.
 *
 * It registers itself with descPanel (image description list) by
 * addSelectionListener(this).
 *
 * A more detailed event models is documented in doc/seqences.mdl
 */
public class ImageDescFrame extends JFrame implements FileListListener, SelectionListener, ObjListListener {

  ImgDescManager m_imgDescManager = new ImgDescManager();

  JPanel contentPane;
  BorderLayout borderLayout1 = new BorderLayout();
  TitledBorder titledBorder1;
  Border border1;


  //Construct the frame
  public ImageDescFrame() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    // add this to listen to image desc manager
    m_imgDescManager.addFileListListener(this);
    m_imgDescManager.addObjListListener(this);
    // add this to listen to image list
    imgList.addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) imgListSelectionChanged(e);
      }
    });
    // add this to listen to desc changes
    descPanel.addSelectionListener(this);
  }

  //Component initialization
  private void jbInit() throws Exception  {
    //setIconImage(Toolkit.getDefaultToolkit().createImage(ImageDescFrame.class.getResource("[Your Icon]")));
    contentPane = (JPanel) this.getContentPane();
    titledBorder1 = new TitledBorder("");
    border1 = BorderFactory.createEtchedBorder(Color.white,new Color(148, 145, 140));
    contentPane.setBorder(BorderFactory.createEtchedBorder(Color.white,new Color(134, 134, 134)));
    contentPane.setMinimumSize(new Dimension(800, 600));
    contentPane.setPreferredSize(new Dimension(800, 600));
    contentPane.setLayout(boxLayout25);

    this.setTitle("Image Description");


    // open button
    openDescButton.setText("Open Desc ...");
    openDescButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        openDescButton_actionPerformed(e);
      }
    });

    // save button
    saveDescButton.setText("Save Desc ...");
    saveDescButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        saveDescButton_actionPerformed(e);
      }
    });

    // button panel 1
    buttonsPanel1.setLayout(new FlowLayout(FlowLayout.LEFT));
    buttonsPanel1.add(openDescButton, null);
    buttonsPanel1.add(saveDescButton, null);

    // add button
    addImgButton.setText("Add Images");
    addImgButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        addImgButton_actionPerformed(e);
      }
    });

    // remove button
    rmImageButton.setText("Remove Images");
    rmImageButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        rmImageButton_actionPerformed(e);
      }
    });

    // clearall button
    clearAllButton.setText("Clear All");
    clearAllButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        clearAllButton_actionPerformed(e);
      }
    });

    // button panel 2
    buttonPanel2.setLayout(new FlowLayout(FlowLayout.LEFT));
    buttonPanel2.add(addImgButton, null);
    buttonPanel2.add(rmImageButton, null);
    buttonPanel2.add(clearAllButton, null);


    // image list
    DefaultListModel imgListModel = new DefaultListModel();
    imgList.setModel(imgListModel);

    // image list scroll pane
    imgListScrollPane.setMinimumSize(new Dimension(400, 160));
    imgListScrollPane.setPreferredSize(new Dimension(400, 160));
    imgListScrollPane.getViewport().add(imgList, null);

    // image preview
    imgPreviewImageViewer.setStyle(2);

    // image preview panel
    imgPreviewPanel.setBorder(BorderFactory.createEtchedBorder());
    imgPreviewPanel.setMinimumSize(new Dimension(400, 300));
    imgPreviewPanel.setPreferredSize(new Dimension(400, 300));
    imgPreviewPanel.setLayout(borderLayout2);
    imgPreviewPanel.add(imgPreviewImageViewer, BorderLayout.CENTER);

    // left panel
    leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
    leftPanel.add(Box.createRigidArea(new Dimension(10, 10)));
    leftPanel.add(buttonsPanel1, null);
    leftPanel.add(buttonPanel2, null);
    leftPanel.add(Box.createRigidArea(new Dimension(10, 10)));
    leftPanel.add(imgListScrollPane, null);
    leftPanel.add(Box.createRigidArea(new Dimension(10, 5)));
    leftPanel.add(imgPreviewPanel, null);
    leftPanel.add(Box.createRigidArea(new Dimension(10, 10)));


    // desc panel
    descPanel.setBorder(BorderFactory.createEtchedBorder());
    descPanel.setMinimumSize(new Dimension(370, 500));
    descPanel.setPreferredSize(new Dimension(370, 500));

    // right panel
    rightPanel.setMinimumSize(new Dimension(370, 500));
    rightPanel.setLayout(boxLayout21);
    boxLayout21.setAxis(BoxLayout.Y_AXIS);
    rightPanel.add(Box.createRigidArea(new Dimension(10, 10)));
    rightPanel.add(descPanel, null);
    rightPanel.add(Box.createRigidArea(new Dimension(10, 10)));

    // content panel
    contentPane.add(Box.createRigidArea(new Dimension(10, 10)));
    contentPane.add(leftPanel, null);
    contentPane.add(Box.createRigidArea(new Dimension(10, 10)));
    contentPane.add(rightPanel, null);
    contentPane.add(Box.createRigidArea(new Dimension(10, 10)));
  }

  //Overridden so we can exit when window is closed
  protected void processWindowEvent(WindowEvent e) {
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      if (m_imgDescManager.getFiles().size() > 0) {  // there are image files
        int result = JOptionPane.showConfirmDialog(this,
            "Do you want to save the descriptions before exit?");
        if (result == JOptionPane.YES_OPTION) {
          saveDescButton_actionPerformed(null);
        }
        else if (result == JOptionPane.CANCEL_OPTION) {
          return;
        }
      }
      super.processWindowEvent(e);
      System.exit(0);
    }
    super.processWindowEvent(e);
  }

  void openDescButton_actionPerformed(ActionEvent e) {
    if (m_descChanged) {
      syncImgDescManager();
      m_descChanged = false;
    }
    JFileChooser fileChooser = new JFileChooser(".");
    int status = fileChooser.showOpenDialog(null);
    if (status == JFileChooser.APPROVE_OPTION) {
      File selectedFile = fileChooser.getSelectedFile();
      m_imgDescManager.readFromFile(selectedFile);
    }
  }

  private void syncImageListPane() {
    Set img_list = m_imgDescManager.getFiles();
    System.out.println("image num : " + img_list.size());

    Vector img_list_vect = new Vector(img_list);
    Collections.sort(img_list_vect);

    DefaultListModel model = (DefaultListModel)imgList.getModel();
    model.removeAllElements();
    Iterator iter = img_list_vect.iterator();
    while(iter.hasNext()) {
      model.addElement(iter.next());
    }

    System.out.println("model size = " + model.getSize());

    // redraw
    imgListScrollPane.validate();
    imgList.repaint();
  }

  public void FileAdded(FileListEvent e) {
    System.out.println("got file added event");
    if (e.getSource() instanceof ImgDescManager) {
      // new files added through manager
      // update the image list pane
      syncImageListPane();
    }
  }
  public void FileRemoved(FileListEvent e) {
    /**@todo: Implement this imgdescgui.FileListListener method*/
    throw new java.lang.UnsupportedOperationException("Method FileRemoved() not yet implemented.");
  }

  private Object[] old_img_names = new Object[0];
  private boolean m_descChanged = false;
  JPanel rightPanel = new JPanel();
  JPanel leftPanel = new JPanel();
  MultiSelectPanel descPanel = new MultiSelectPanel();
  BoxLayout2 boxLayout21 = new BoxLayout2();
  BoxLayout2 boxLayout23 = new BoxLayout2();
  JButton rmImageButton = new JButton();
  JPanel buttonPanel2 = new JPanel();
  JButton addImgButton = new JButton();
  BoxLayout2 boxLayout24 = new BoxLayout2();
  JButton clearAllButton = new JButton();
  BoxLayout2 boxLayout22 = new BoxLayout2();
  JPanel buttonsPanel1 = new JPanel();
  JButton openDescButton = new JButton();
  JButton saveDescButton = new JButton();
  JScrollPane imgListScrollPane = new JScrollPane();
  JList imgList = new JList();
  BorderLayout borderLayout2 = new BorderLayout();
  ImageViewer imgPreviewImageViewer = new ImageViewer();
  JPanel imgPreviewPanel = new JPanel();
  BoxLayout2 boxLayout25 = new BoxLayout2();

  private void syncDescPanel() {
    // image selection changed
    Object img_names[] = imgList.getSelectedValues();

    // update the description pane
    descPanel.setEnabled(img_names.length > 0);

    HashMap the_desc = m_imgDescManager.getObjCount(img_names);
    descPanel.setStatusForAll(MultiSelectPanel.UNSELECTED);
    int obj_num = img_names.length;
    Iterator iter = the_desc.keySet().iterator();
    while (iter.hasNext()) {
      String key = (String) iter.next();
      int count = ( (Integer) the_desc.get(key)).intValue();
      if (count == 0) {
      }
      else if (count < obj_num) { // some has, some not
        descPanel.addSelection(key, descPanel.UNKNOWN);
      }
      else if (count == obj_num) { // all has
        descPanel.addSelection(key, descPanel.SELECTED);
      }
      else {
        System.err.println("the found object count is greater than expected");
      }
    }
    descPanel.redraw();
  }
  public void imgListSelectionChanged(ListSelectionEvent e) {

//    if (m_descChanged) {
//      syncImgDescManager(old_img_names);
//      m_descChanged = false;
//    }

    // image selection changed
    syncDescPanel();

    // update image preview window
    String image_path = Configuration.getParameter("IMAGE_PATH", "");

    Object img_names[] = imgList.getSelectedValues();
    try {
      if (img_names.length > 0) {
        String preview_img = (String) img_names[img_names.length - 1];
        Image image = yi.util.io.ImageReader.readImageFile(
            image_path + preview_img);
        imgPreviewImageViewer.setImage(image);
      } else {
        imgPreviewImageViewer.setImage(null);
      }

      imgPreviewImageViewer.repaint();
    }
    catch (Exception exception) {
      exception.printStackTrace();
    }
    old_img_names = (Object[]) img_names.clone();
  }
  private void syncImgDescManager() {
    // synch ImgDescManager with the selection changes
    syncImgDescManager(imgList.getSelectedValues());
  }

  private void syncImgDescManager(Object[] img_names) {
    // synch ImgDescManager with the selection changes
    // get the selection status
    HashMap status = descPanel.getSelectionStatus();
    for (int i=0; i<img_names.length; i++) {
      String file = (String)img_names[i];
      Iterator iter = status.keySet().iterator();
      while (iter.hasNext()) {
        String key = (String) iter.next();
        Integer s = (Integer) status.get(key);

        if (s.compareTo(MultiSelectPanel.SELECTED) == 0) {
          m_imgDescManager.addDesc(file, key);
        }
        else if (s.compareTo(MultiSelectPanel.UNSELECTED) == 0) {
          m_imgDescManager.remove(file, key);
        }
      }
    }

  }
  void saveDescButton_actionPerformed(ActionEvent e) {
    if (m_descChanged) {
      syncImgDescManager();
      m_descChanged = false;
    }
    JFileChooser fileChooser = new JFileChooser(".");
    int status = fileChooser.showSaveDialog(null);
    if (status == JFileChooser.APPROVE_OPTION) {
      File selectedFile = fileChooser.getSelectedFile();
      m_imgDescManager.writeToFile(selectedFile);
    }
  }

  public void selectionSelected(SelectionEvent e, String selection) {
    Object[] img_names = imgList.getSelectedValues();
    for (int i=0; i<img_names.length; i++) {
       String file = (String)img_names[i];
       m_imgDescManager.addDesc(file, selection);
    }
  }

  public void selectionUnselected(SelectionEvent e, String selection) {
    Object[] img_names = imgList.getSelectedValues();
    for (int i=0; i<img_names.length; i++) {
       String file = (String)img_names[i];
       m_imgDescManager.remove(file, selection);
    }

  }

  public void selectionRemoved(SelectionEvent e, String selection) {
    m_imgDescManager.removeObj(selection);
  }

  void addImgButton_actionPerformed(ActionEvent e) {
    JFileChooser fileChooser = new JFileChooser(".");
    javax.swing.filechooser.FileFilter imageFilter = new ExtensionFileFilter("Image Files", new String[]{"JPG", "JPEG", "gif"});
    fileChooser.addChoosableFileFilter(imageFilter);
    fileChooser.addChoosableFileFilter(fileChooser.getAcceptAllFileFilter());
    fileChooser.setAccessory(new ImagePreviewAccessory(fileChooser));
    fileChooser.setMultiSelectionEnabled(true);
    int status = fileChooser.showOpenDialog(null);
    if (status == JFileChooser.APPROVE_OPTION) {
      File[] selectedFile = fileChooser.getSelectedFiles();
      // add images to image desc manager
      m_imgDescManager.addFiles(selectedFile);
    }
  }

  void rmImageButton_actionPerformed(ActionEvent e) {
    Object[] img_names = imgList.getSelectedValues();
    String[] img_names_str = yi.util.data.Conversion.toStringArray(img_names);
    m_imgDescManager.removeFiles(img_names_str);
  }

  void clearAllButton_actionPerformed(ActionEvent e) {
    m_imgDescManager.clearAll();
  }
  public void ObjAdded(ObjListEvent e) {
    descPanel.removeAllSelectons();
    Collection objs = m_imgDescManager.getObjects();
    Iterator iter = objs.iterator();
    while (iter.hasNext()) {
      descPanel.addSelection((String)iter.next(), MultiSelectPanel.UNSELECTED);
    }
    syncDescPanel();
  }
  public void ObjRemoved(ObjListEvent e) {
    /**@todo Implement this imgdescgui.ObjListListener method*/
    throw new java.lang.UnsupportedOperationException("Method ObjRemoved() not yet implemented.");
  }

}