package com.vistech.util;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.image.*;
import com.vistech.util.*;
import com.vistech.events.*;
import java.util.*;
import javax.swing.table.*;

public class FileSelector extends JPanel{
   protected JList itemList;
   protected String[] fileList;
   protected JTree tree;
   protected String curDir = ".";
   protected String topNode= ".";
   protected File currentDir;
   protected char separator = File.separatorChar;
   protected JTextField dirField, filterField;
   protected JButton upButton;
   protected String filterString = ".jpg,.jpeg,.gif,.bmp,.png,.pnm,.pbm,.bmp,.tif,.tiff";
   protected String fString[] = {".jpg",".jpeg", ".gif",".tif",".tiff", ".bmp", ".png", ".fpx", ".ppm", ".pnm",".pbm"};
   protected JScrollPane treeView;
   private Vector listSelListeners = new Vector();
   protected int selectionMode = ListSelectionModel.SINGLE_SELECTION;
   protected String[][] fileInfoList = new String[1][3];
   protected String columnNames[] = {"File", "Size"};
   protected JTable fileInfoTable;

   public FileSelector(){
      try{
        currentDir = new File(".");
        curDir = currentDir.getAbsolutePath();
        topNode = curDir;
        //System.out.println("cur dir "+ curDir);
      }catch (Exception e){}
      createUI();
   }

   public void setPath(File path){currentDir = path;}
   public File gePath(){ return currentDir;}


   
   public void createUI (){
      JPanel pan = new JPanel();
      JPanel dirP = new JPanel();
      JLabel dirL = new JLabel("Directory ", SwingConstants.RIGHT);
      dirField = new JTextField(15);
      if(curDir != null) dirField.setText(curDir);

      JPanel filtP= new JPanel();
      JLabel filtL = new JLabel("Filter ", SwingConstants.RIGHT);

      filterField = new JTextField(15);
      filterField.setText(filterString);
      filtP.add(filtL);
      filtP.add(filterField);

      upButton = new JButton("^");

      tree = createTreeView();
      treeView = new JScrollPane(tree);
      treeView.setPreferredSize(new Dimension(300,600));
      treeView.setBackground(Color.gray);

      GridBagLayout  gb = new GridBagLayout() ;
      GridBagConstraints c = new GridBagConstraints();
      setLayout(gb);
      c.weightx = 0.2; c.weighty = 0.1;
      c.fill =  GridBagConstraints.BOTH;
      c.insets = new Insets(5,1, 1,1);
      gb.setConstraints(filtL, c);
      add(filtL);
      c.insets = new Insets(5,1, 1,1);
      c.gridwidth =  GridBagConstraints.REMAINDER;
      c.weightx = 1.0; c.weighty = 0.1;
      gb.setConstraints(filterField, c);
      add(filterField);
      c.insets = new Insets(1,1, 1,1);
      c.gridwidth = 1;
      c.weightx = 0.2; c.weighty = 0.1;
      gb.setConstraints(dirL, c);
      add(dirL);
      c.insets = new Insets(1,1, 1,1);
      c.weightx = 1.0; c.weighty = 0.1;

      gb.setConstraints(dirField, c);
      add(dirField);
      c.weightx = 0.2; c.weighty = 0.1;
      c.gridwidth =  GridBagConstraints.REMAINDER;
      gb.setConstraints(upButton, c);
      add(upButton);
      c.fill =  GridBagConstraints.BOTH;
      c.weightx = 1.0; c.weighty = 5.0;
      fileInfoTable = createFileInfoTable();
      clickToLoad(fileInfoTable);
      fileInfoTable.setPreferredSize(new Dimension(70,600));
      JScrollPane jsp = new JScrollPane(fileInfoTable);
      jsp.setPreferredSize(new Dimension(60,600));
      JSplitPane vsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeView,jsp);
      gb.setConstraints(treeView, c);
      add(treeView);
      vsp.setDividerLocation(120);
      vsp.setDividerSize(3);
      handleEvents();
      revalidate();
   }
 
   protected void handleEvents() {
      filterField.addActionListener(
            new ActionListener(){
               public void actionPerformed(ActionEvent e){
                  String filterString = ((JTextField)(e.getSource())).getText();
                  if(filterString == null) return;
                  StringTokenizer st = new StringTokenizer(filterString, ",");
                  int num = st.countTokens();
                  fString = new String[num];
                  int i=0;
                  while(st.hasMoreTokens()){
                        String str = st.nextToken();
                        String name = str.trim();
                        fString[i++] = name;
                  }
                  updateTreeView(topNode);
                  treeView.revalidate();
                  FileSelector.this.revalidate();
               }
            }
      );
      dirField.addActionListener(
            new ActionListener(){
               public void actionPerformed(ActionEvent e){
                  String currentDirStr = ((JTextField)(e.getSource())).getText();
                  if(currentDirStr != null){
                     curDir = currentDirStr;
                     try {
                     currentDir = new File(curDir);
                     topNode = curDir;
                     updateTreeView(curDir);
                     treeView.revalidate();
                     FileSelector.this.revalidate();
                    } catch(Exception e1) {}
                  }
               }
            }
      );
      upButton.addActionListener(
            new ActionListener(){
               public void actionPerformed(ActionEvent e){
                  try {
                    File dir = new File(topNode);
                    String currentDirStr = dir.getParent();
                    curDir = currentDirStr;
                    currentDir = new File(curDir);
                    topNode = curDir;
                    dirField.setText(curDir);
                    updateTreeView(curDir);
                    treeView.revalidate();
                    FileSelector.this.revalidate();
                 }catch (Exception e1) {}
               }
            }
      );
   }
   protected JTree createTreeView() {
      String[] filelist = listFilteredFiles(curDir, fString);
        if(filelist == null) return null;
      for(int i=0;i<filelist.length;i++){
          //System.out.println(filelist[i]);
        }
      DefaultMutableTreeNode top = new DefaultMutableTreeNode(curDir);
      createNewNodes(top, filelist);

      JTree tree = new JTree(top);
      tree.getSelectionModel().setSelectionMode
                           (TreeSelectionModel.SINGLE_TREE_SELECTION);
      tree.addTreeSelectionListener(
             new TreeSelectionListener() {
             public void valueChanged(TreeSelectionEvent e) {
                 TreePath selpath = e.getPath();
                 expandNode(selpath);
              }
         });
       return tree;
   }

    protected JTree newTreeView(String curDir) {
       String[] filelist = listFilteredFiles(curDir, fString);
       DefaultMutableTreeNode top = new DefaultMutableTreeNode(curDir);
       createNewNodes(top, filelist);

       JTree tree = new JTree(top);
       tree.getSelectionModel().setSelectionMode
                            (TreeSelectionModel.SINGLE_TREE_SELECTION);
       tree.addTreeSelectionListener(
             new TreeSelectionListener() {
             public void valueChanged(TreeSelectionEvent e) {
                 TreePath selpath = e.getPath();
                 expandNode(selpath);
              }
       });
       tree.revalidate();
       return tree;
   }

   protected void updateTreeView(String curDir) {
       String[] filelist = listFilteredFiles(curDir, fString);
       DefaultMutableTreeNode top = new DefaultMutableTreeNode(curDir);
       createNewNodes(top, filelist);
       DefaultTreeModel dft = new DefaultTreeModel(top);
       tree.setModel(dft);
   }

   private void createNewNodes(DefaultMutableTreeNode top, String[] flist) {
       if((top == null) || (flist == null)) return;
       DefaultMutableTreeNode file = null;
       for(int i=0; i< flist.length;i++){
           try{
             File fl = new File(flist[i]);
             if(fl.isDirectory()) file = new DefaultMutableTreeNode(flist[i], true);
             else file = new DefaultMutableTreeNode(flist[i]);
             top.add(file);
           } catch(Exception e){System.out.println(e);}
       }
   }

   private void expandNode(TreePath selpath) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                                              (selpath.getLastPathComponent());
      Object[] pathobj = selpath.getPath();
      if(pathobj == null) return;
      StringBuffer path=null;
      for(int i=0;i<pathobj.length;i++){
          if(path== null) path= new StringBuffer(pathobj[0].toString());
          else path.append(pathobj[i].toString());
          if(i != pathobj.length-1) path.append(separator);
      }
      try {
         if(node.isLeaf()){
            String filename = path.toString();
            long len = path.length();
            if(isDirectory(path.toString())){
               tree.collapsePath(selpath);
               curDir = path.toString();
               File dir = new File(curDir);
               currentDir = dir;
               File[] flist = dir.listFiles();
               if(flist == null) return;
               String[] filelist = filterFileNames(flist, fString);
               if(filelist == null) return;
               createNewNodes(node,filelist);
            } else {
             
               ListSelectEvent ls = new ListSelectEvent(
                                         this,
                                         null,
                                         null,
                                         new String[] {filename});
                 fireListSelectEvent(ls);
              }
            }
      } catch (Exception e){System.out.println(e);}
    }

    protected JTable createFileInfoTable(){

        TableModel dataModel = new AbstractTableModel() {
          public String getColumnName(int column) {
             return  columnNames[column];
          }
          public int getColumnCount() {
             return columnNames.length;
          }
          public int getRowCount() {
             if(fileInfoList == null) return 0;
             return fileInfoList.length;
          }
          public Object getValueAt(int row, int col) {
             if(fileInfoList == null) return null;
             if((row >= fileInfoList.length)||(col >= fileInfoList[0].length)) return null;
             return fileInfoList[row][col];
         }
      };
      JTable table = new JTable(dataModel);
      return new JTable(dataModel);
    }

    protected void clickToLoad(JTable tb){
     final JTable table = tb;
     ListSelectionModel lsm = table.getSelectionModel();
        lsm.setSelectionMode(selectionMode);
        lsm.addListSelectionListener(
             new ListSelectionListener() {
               public void valueChanged(ListSelectionEvent e){
                  int row = table.getSelectedRow();
                  String filename = fileInfoList[row][0];
                  ListSelectEvent ls = new ListSelectEvent(
                                       this,
                                       null,
                                       currentDir,
                                       new String[] {filename});
                  fireListSelectEvent(ls);
              }
            }
         );
     }

    public String[] listFilteredFiles(String dir, String[] filt){
      try {
      File direct = new File(dir);
      File[] flist = direct.listFiles();
      if(flist == null) return null;
      String[] ftlist = filterFileNames(flist, filt);
      for(int i=0; i< ftlist.length;i++){
          //System.out.println(flist[i]);
      }
      return ftlist;
      } catch (Exception e) {return null;}
   }

    public String[] filterFileNames(File filelist[], String fstr[]){
      Vector fl = new Vector();
      Vector finfo = new Vector();
      int j =0;
      int numfiles = filelist.length;

      for(int i=0; i< filelist.length;i++){
          try {
            if(filelist[i].isDirectory()) {
               fl.add(filelist[i].getName()); j++;
               continue;
            }
          } catch (Exception e) {continue;}
          String fi[] = new String[2];
          for(int k =0; k< fstr.length;k++){
              if(filelist[i].getName().endsWith(fstr[k])){
                 fl.add(filelist[i].getName());
                 fi[0] = filelist[i].getName();
                 long len = filelist[i].length();
                 int size = (int)(len/1000);
                 fi[1] = Integer.toString(size)+"k";
                 finfo.add(fi);
                 //long datems =   filelist[i].lastModified();
                 //Date date = new Date(datems);
                 //fileInfoList[i][2] =date.toString();
                 j++;
                 break;
              };
          }

      }
      repaint();
      int size = fl.size();
      String[] newfl = new String[size];
      size = finfo.size();

      fl.copyInto(newfl);
      fileInfoList = new String[size][3];
      finfo.copyInto(fileInfoList);
      return newfl;
   }
 
   public static String[] listFiles(String userDir) {
      String fl[] = null; 
      try {
         File dir = new File(userDir);
         fl = dir.list();
         //System.out.println(fl[0]);
      } catch (Exception e){System.out.println(e);}
      return fl;
   }

   public static boolean isDirectory(String file){
      try{
        File fl= new File(file);
        if(fl.isDirectory()) return true;
      } catch (Exception e){System.out.println(e);}
      return false;
   }

   private void doubleClick(int selrow, TreePath selpath) {
       if(!tree.isCollapsed(selpath)) tree.collapsePath(selpath);  
       else expandNode(selpath);
   }
 
   private void singleClick(int selrow, TreePath selpath) {
       if(tree.isCollapsed(selpath)) expandNode(selpath);
   }

   public void addListSelectListener(ListSelectListener il){
       listSelListeners.addElement(il);
   }

   public void removeListSelectListener(ListSelectListener il){
      if(!(listSelListeners.isEmpty())) listSelListeners.removeElement(il);
   }

   protected void fireListSelectEvent(ListSelectEvent lse){
      if(listSelListeners.isEmpty()) return;
      Vector lstn = new Vector();
      synchronized(this){
          lstn = (Vector)listSelListeners.clone();
      }
      for(Enumeration e=lstn.elements();e.hasMoreElements();){
          ((ListSelectListener)(e.nextElement())).load(lse);
      }
   }

   public static void main(String args[]){
      FileSelector fc = new FileSelector();
  }
}
