/* CachePane.java -- Displays the specified folder and allows modification to its content.
Copyright (C) 2010 Red Hat

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package net.sourceforge.jnlp.controlpanel;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;

import net.sourceforge.jnlp.cache.CacheDirectory;
import net.sourceforge.jnlp.cache.DirectoryNode;
import net.sourceforge.jnlp.config.DeploymentConfiguration;
import net.sourceforge.jnlp.runtime.Translator;
import net.sourceforge.jnlp.util.FileUtils;

public class CachePane extends JPanel {

    JDialog parent;
    DeploymentConfiguration config;
    private String location;
    private JComponent defaultFocusComponent;
    DirectoryNode root;
    String[] columns = { Translator.R("CVCPColName"),
            Translator.R("CVCPColPath"),
            Translator.R("CVCPColType"),
            Translator.R("CVCPColDomain"),
            Translator.R("CVCPColSize"),
            Translator.R("CVCPColLastModified") };
    JTable cacheTable;

    /**
     * Creates a new instance of the CachePane.
     * 
     * @param parent The parent dialog that uses this pane.
     * @param config The DeploymentConfiguration file.
     */
    public CachePane(JDialog parent, DeploymentConfiguration config) {
        super(new BorderLayout());
        this.parent = parent;
        this.config = config;
        location = config.getProperty(DeploymentConfiguration.KEY_USER_CACHE_DIR);

        addComponents();
    }

    /**
     * Add components to the pane.
     */
    private void addComponents() {
        JPanel topPanel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;

        DefaultTableModel model = new DefaultTableModel(columns, 0) {
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        cacheTable = new JTable(model);
        cacheTable.setAutoCreateRowSorter(true);
        cacheTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        cacheTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
        cacheTable.setPreferredScrollableViewportSize(new Dimension(600, 200));
        cacheTable.setFillsViewportHeight(true);
        JScrollPane scrollPane = new JScrollPane(cacheTable);

        populateTable();

        c.weightx = 1;
        c.weighty = 1;
        c.gridx = 0;
        c.gridy = 0;
        topPanel.add(scrollPane, c);
        this.add(topPanel, BorderLayout.CENTER);
        this.add(createButtonPanel(), BorderLayout.SOUTH);

    }

    /**
     * Create the buttons panel.
     * 
     * @return JPanel containing the buttons.
     */
    private Component createButtonPanel() {
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0));
        JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
        JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));

        List<JButton> buttons = new ArrayList<JButton>();

        JButton deleteButton = new JButton(Translator.R("CVCPButDelete"));
        deleteButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int row = cacheTable.getSelectedRow();
                try {
                    if (row == -1 || row > cacheTable.getRowCount() - 1)
                        return;
                    int modelRow = cacheTable.convertRowIndexToModel(row);
                    DirectoryNode fileNode = ((DirectoryNode) cacheTable.getModel().getValueAt(modelRow, 0));
                    if (fileNode.getFile().delete()) {
                        fileNode.getParent().removeChild(fileNode);
                        FileUtils.deleteWithErrMesg(fileNode.getInfoFile());
                        ((DefaultTableModel) cacheTable.getModel()).removeRow(modelRow);
                        cacheTable.getSelectionModel().setSelectionInterval(row, row);
                        CacheDirectory.cleanParent(fileNode);
                    }
                } catch (Exception exception) {
                    //ignore
                }
            }
        });
        buttons.add(deleteButton);

        JButton refreshButton = new JButton(Translator.R("CVCPButRefresh"));
        refreshButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                populateTable();
            }
        });
        buttons.add(refreshButton);

        JButton doneButton = new JButton(Translator.R("ButDone"));
        doneButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                parent.dispose();
            }
        });

        int maxWidth = 0;
        int maxHeight = 0;
        for (JButton button : buttons) {
            maxWidth = Math.max(button.getMinimumSize().width, maxWidth);
            maxHeight = Math.max(button.getMinimumSize().height, maxHeight);
        }

        int wantedWidth = maxWidth + 10;
        int wantedHeight = maxHeight;
        for (JButton button : buttons) {
            button.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
            leftPanel.add(button);
        }

        doneButton.setPreferredSize(new Dimension(wantedWidth, wantedHeight));
        rightPanel.add(doneButton);
        buttonPanel.add(leftPanel);
        buttonPanel.add(rightPanel);

        return buttonPanel;
    }

    /**
     * Populate the table with fresh data. Any manual updates to the cache
     * directory will be updated in the table.
     */
    private void populateTable() {
        ((DefaultTableModel) cacheTable.getModel()).setRowCount(0); //Clears the table
        for (Object[] v : generateData(root))
            ((DefaultTableModel) cacheTable.getModel()).addRow(v);
    }

    /**
     * This creates the data for the table.
     * 
     * @param root The location of cache data.
     * @return ArrayList containing an Object array of data for each row in the table.
     */
    private ArrayList<Object[]> generateData(DirectoryNode root) {
        root = new DirectoryNode("Root", location, null);
        CacheDirectory.getDirStructure(root);
        ArrayList<Object[]> data = new ArrayList<Object[]>();

        for (DirectoryNode type : root.getChildren()) {
            for (DirectoryNode domain : type.getChildren()) {
                for (DirectoryNode leaf : CacheDirectory.getLeafData(domain)) {
                    Object[] o = { leaf,
                            leaf.getFile().getAbsolutePath(),
                            type,
                            domain,
                            leaf.getFile().length(),
                            new SimpleDateFormat("MM/dd/yyyy").format(leaf.getFile().lastModified()) };
                    data.add(o);
                }
            }
        }

        return data;
    }

    /**
     * Put focus onto default button.
     */
    public void focusOnDefaultButton() {
        if (defaultFocusComponent != null) {
            defaultFocusComponent.requestFocusInWindow();
        }
    }
}