import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.GridBagConstraints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;

public class SimpleFileManager {
    private Desktop desktop;
    private JLabel label;
    private JPanel panel;
    private Map<Component, File> items;
    private Component selected;
    
    public SimpleFileManager(String directory) throws IOException {
        if (!Desktop.isDesktopSupported()) {
            throw new IllegalStateException("Desktop doesn't support.");
        }

        desktop = Desktop.getDesktop();

        JFrame frame = new JFrame("Simple File Manager");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        label = new JLabel(new File(directory).getPath());
        frame.add(label, BorderLayout.NORTH);

        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        panel.setBackground(Color.WHITE);

        JScrollPane pane = new JScrollPane(panel,
                               JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                               JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        frame.add(pane, BorderLayout.CENTER);

        frame.setSize(300, 500);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        extractFile(directory);
    }

    private void extractFile(String directory) throws IOException {
        File dir = new File(directory);
        extractFile(dir);
    }

    private void extractFile(File dir) throws IOException {
        items = new HashMap<Component, File>();

        if (!dir.exists() || !dir.isDirectory()) {
            throw new IOException();
        }

        label.setText(dir.getPath());

        panel.removeAll();
        panel.repaint();

        GridBagConstraints constraints = new GridBagConstraints();
        constraints.weightx = 1.0;
        constraints.gridwidth = 1;
        constraints.weighty = 1.0;
        constraints.gridheight = 1;
        
        JLabel item;
        File parent = new File(dir.getCanonicalPath() + "/..");
        if (parent.exists() 
            && !parent.getCanonicalFile().equals(dir.getCanonicalFile())) {
            item = new JLabel("..",
                              UIManager.getIcon("FileView.directoryIcon"),
                              JLabel.TRAILING);
            addItem(item, parent);
        }

        File[] files = dir.listFiles();
        java.util.List<File> directories = new ArrayList<File>();
        java.util.List<File> fileList = new ArrayList<File>();
        for (File file: files) {
            if (file.isDirectory()) {
                directories.add(file);
            } else {
                fileList.add(file);
            }
        }

        for (File directory: directories) {
            item = new JLabel(directory.getName(),
                              UIManager.getIcon("FileView.directoryIcon"),
                              JLabel.TRAILING);

            addItem(item, directory);
        }

        for (File file: fileList) {
            item = new JLabel(file.getName(),
                              UIManager.getIcon("FileView.fileIcon"),
                              JLabel.TRAILING);

            addItem(item, file);
        }

        panel.revalidate();
    }

    private void addItem(JLabel item, File file) {
        item.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent event) {
                    if (event.getClickCount() > 1) {
                        if (selected != null) {
                            selected.setEnabled(true);
                        }
                        Component comp = event.getComponent();
                        selected = comp;
                        selected.setEnabled(false);
                        open(comp);
                    }
                }
            });

        panel.add(item);
        items.put(item, file);
    }

    private void open(Component source) {
        File file = items.get(source);

        try {
            file = file.getCanonicalFile();

            if (file.isDirectory()) {
                extractFile(file);
                return;
            }

            desktop.open(file);
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(source, file.getName() + " can't open.",
                                          "Warning",
                                          JOptionPane.WARNING_MESSAGE);
        }
    }
    
    public static void main(String[] args) {
        if (args.length > 0) {
            try {
                new SimpleFileManager(args[0]);
            } catch (IOException ex) {
                System.err.println(args[0] + " can't open.");
                ex.printStackTrace();
            }
        } else {
            try {
                new SimpleFileManager(".");
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

