/*
 *  PHEX - The pure-java Gnutella-servent.
 *  Copyright (C) 2001 - 2006 Phex Development Group
 *
 *  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 phex.gui.tabs.library;

import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;

import org.apache.commons.lang.SystemUtils;

import phex.common.ServiceManager;
import phex.common.ThreadPool;
import phex.common.URN;
import phex.common.format.NumberFormatUtils;
import phex.event.ShareChangeListener;
import phex.gui.actions.FWAction;
import phex.gui.actions.GUIActionPerformer;
import phex.gui.common.*;
import phex.gui.common.table.FWSortedTableModel;
import phex.gui.common.table.FWTable;
import phex.gui.common.table.FWTableColumnModel;
import phex.gui.dialogs.ExportDialog;
import phex.gui.dialogs.FilterLibraryDialog;
import phex.gui.tabs.FWTab;
import phex.share.*;
import phex.utils.*;
import phex.xml.sax.gui.DGuiSettings;
import phex.xml.sax.gui.DTable;
import phex.xml.sax.gui.DTableColumnList;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

public class LibraryTab extends FWTab
{
    private static final String SHARED_FILES_TABLE_IDENTIFIER = "SharedFilesTable";

    private JLabel sharedFilesLabel;

    private FWTable sharedFilesTable;

    private JTree mainTree;

    //private FileSystemTreeModel fileSystemTreeModel;
    private SharingTreeModel sharingTreeModel;

    private FWPopupMenu fileTreePopup;
    private FWPopupMenu fileTablePopup;

    private JScrollPane sharedFilesTableScrollPane;

    private SharedFilesTableModel sharedFilesModel;

    private FWTableColumnModel sharedFilesColumnModel;

    public LibraryTab()
    {
        super(MainFrame.LIBRARY_TAB_ID, Localizer.getString("Library"),
            GUIRegistry.getInstance().getPlafIconPack().getIcon("Library.Tab"),
            Localizer.getString("TTTLibrary"), Localizer
                .getChar("LibraryMnemonic"), KeyStroke.getKeyStroke(Localizer
                .getString("LibraryAccelerator")), MainFrame.LIBRARY_TAB_INDEX);
    }

    public void initComponent(DGuiSettings guiSettings)
    {
        CellConstraints cc = new CellConstraints();
        FormLayout tabLayout = new FormLayout("2dlu, fill:d:grow, 2dlu", // columns
            "2dlu, fill:p:grow, 2dlu"); //rows
        PanelBuilder tabBuilder = new PanelBuilder(tabLayout, this);
        JPanel contentPanel = new JPanel();
        FWElegantPanel elegantPanel = new FWElegantPanel( Localizer.getString("Library"),
            contentPanel );
        tabBuilder.add(elegantPanel, cc.xy(2, 2));
        
        FormLayout contentLayout = new FormLayout("fill:d:grow", // columns
            "fill:d:grow"); //rows
        PanelBuilder contentBuilder = new PanelBuilder(contentLayout, contentPanel);
        
        
        MouseHandler mouseHandler = new MouseHandler();
        
        JPanel treePanel = createTreePanel( mouseHandler );
        JPanel tablePanel = createTablePanel( guiSettings, mouseHandler );

        JSplitPane splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
            treePanel, tablePanel );
        splitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
        splitPane.setDividerSize(4);
        splitPane.setOneTouchExpandable(false);
        contentBuilder.add(splitPane, cc.xy(1, 1));
       

        sharedFilesLabel = new JLabel( " " );
        sharedFilesLabel.setHorizontalAlignment( JLabel.RIGHT );
        elegantPanel.addHeaderPanelComponent(sharedFilesLabel, BorderLayout.EAST );
        ShareManager.getInstance().getSharedFilesService().addSharedFilesChangeListener(
            new SharedFilesChangeHandler() );
        
        fileTreePopup = new FWPopupMenu();
        fileTablePopup = new FWPopupMenu();
        
        FWAction action;
        
        action = getTabAction( ADD_SHARE_FOLDER_ACTION_KEY );
        fileTreePopup.addAction( action );
        action = getTabAction( REMOVE_SHARE_FOLDER_ACTION_KEY );
        fileTreePopup.addAction( action );
        
        if ( SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC_OSX )
        {
            action = getTabAction( EXPLORE_FOLDER_ACTION_KEY );
            fileTreePopup.addAction( action );
        }
        
        action = getTabAction( OPEN_FILE_ACTION_KEY );
        fileTablePopup.addAction( action );
        
        action = getTabAction( VIEW_BITZI_ACTION_KEY );
        fileTablePopup.addAction( action );
        
        fileTablePopup.addSeparator();
        fileTreePopup.addSeparator();
        
        action = getTabAction( RESCAN_ACTION_KEY );
        fileTablePopup.addAction( action );
        fileTreePopup.addAction( action );
        
        action = getTabAction( EXPORT_ACTION_KEY );
        fileTablePopup.addAction( action );
        fileTreePopup.addAction( action );
        
        action = getTabAction( FILTER_ACTION_KEY );
        fileTablePopup.addAction( action );
        fileTreePopup.addAction( action );
    }
    
    private JPanel createTreePanel(MouseHandler mouseHandler )
    {
        JPanel panel = new JPanel();
        CellConstraints cc = new CellConstraints();
        FormLayout layout = new FormLayout("fill:d:grow", // columns
            "fill:d:grow, 1dlu, p"); //rows
        PanelBuilder tabBuilder = new PanelBuilder(layout, panel);
        
        sharingTreeModel = new SharingTreeModel();
        mainTree = new JTree( sharingTreeModel );
        mainTree.setMinimumSize( new Dimension( 0, 0 ) );
        mainTree.setRowHeight(0);
        mainTree.setCellRenderer(new SharingTreeRenderer());
        mainTree.addMouseListener(mouseHandler);
        
        mainTree.getSelectionModel().addTreeSelectionListener(
            new SelectionHandler());
        ToolTipManager.sharedInstance().registerComponent( mainTree );
        
        // open up first level of nodes
        TreeNode root = (TreeNode) sharingTreeModel.getRoot();
        int count = root.getChildCount();
        for ( int i = 0; i < count; i++ )
        {
            mainTree.expandPath( new TreePath( new Object[] {root, root.getChildAt(i)} ) );
        }

        JScrollPane treeScrollPane = new JScrollPane(mainTree);
        tabBuilder.add(treeScrollPane, cc.xywh(1, 1, 1, 1));
        
        FWToolBar shareToolbar = new FWToolBar(FWToolBar.HORIZONTAL);
        shareToolbar.setBorderPainted(false);
        shareToolbar.setFloatable(false);
        tabBuilder.add(shareToolbar, cc.xy(1, 3));
        
        FWAction action = new AddShareFolderAction();
        addTabAction( ADD_SHARE_FOLDER_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        action = new RemoveShareFolderAction();
        addTabAction( REMOVE_SHARE_FOLDER_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        if ( SystemUtils.IS_OS_WINDOWS || SystemUtils.IS_OS_MAC_OSX )
        {
            action = new ExploreFolderAction();
            addTabAction( EXPLORE_FOLDER_ACTION_KEY, action );
        }
        
        return panel;
    }
    
    private JPanel createTablePanel(DGuiSettings guiSettings, 
        MouseHandler mouseHandler )
    {
        JPanel panel = new JPanel();
        CellConstraints cc = new CellConstraints();
        FormLayout layout = new FormLayout("fill:d:grow", // columns
            "fill:d:grow, 1dlu, p"); //rows
        PanelBuilder tabBuilder = new PanelBuilder(layout, panel);
        
        sharedFilesModel = new SharedFilesTableModel();
        DTable dTable = GUIUtils.getDGuiTableByIdentifier(guiSettings,
            SHARED_FILES_TABLE_IDENTIFIER);
        buildSharedFilesTableColumnModel(dTable);
        sharedFilesTable = new FWTable(new FWSortedTableModel(
            sharedFilesModel), sharedFilesColumnModel);
        sharedFilesTable.activateAllHeaderActions();
        sharedFilesTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        sharedFilesTable.addMouseListener(mouseHandler);
        sharedFilesTable.getSelectionModel().addListSelectionListener(
            new SelectionHandler());
        sharedFilesTableScrollPane = FWTable
            .createFWTableScrollPane(sharedFilesTable);
        
        tabBuilder.add(sharedFilesTableScrollPane, cc.xy(1, 1));
        
        FWToolBar shareToolbar = new FWToolBar(FWToolBar.HORIZONTAL);
        shareToolbar.setBorderPainted(false);
        shareToolbar.setFloatable(false);
        tabBuilder.add(shareToolbar, cc.xy(1, 3));
        
        FWAction action;
        
        action = new OpenFileAction();
        addTabAction( OPEN_FILE_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        action = new ViewBitziTicketAction();
        addTabAction( VIEW_BITZI_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        shareToolbar.addSeparator();
        
        action = new RescanAction();
        addTabAction( RESCAN_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        action = new ExportAction();
        addTabAction( EXPORT_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        action = new FilterAction();
        addTabAction( FILTER_ACTION_KEY, action );
        shareToolbar.addAction( action );
        
        return panel;
    }

    /**
     * This is overloaded to update the table size for the progress bar on
     * every UI update. Like font size change!
     */
    public void updateUI()
    {
        super.updateUI();
        if (sharedFilesTableScrollPane != null)
        {
            FWTable.updateFWTableScrollPane(sharedFilesTableScrollPane);
        }
    }

    private LibraryNode getSelectedTreeComponent()
    {
        TreePath path = mainTree.getSelectionPath();
        if (path == null)
        {
            return null;
        }
        LibraryNode node = (LibraryNode) path.getLastPathComponent();
        return node;
    }

    //////////////////////////////////////////////////////////////////////////
    /// XML serializing and deserializing
    //////////////////////////////////////////////////////////////////////////

    private void buildSharedFilesTableColumnModel( DTable tableSettings)
    {
        int[] columnIds = SharedFilesTableModel.getColumnIdArray();
        DTableColumnList columnList = null;
        if (tableSettings != null)
        {
            columnList = tableSettings.getTableColumnList();
        }

        sharedFilesColumnModel = new FWTableColumnModel(sharedFilesModel,
            columnIds, columnList);
    }

    public void appendDGuiSettings(DGuiSettings dSettings)
    {
        super.appendDGuiSettings(dSettings);

        DTableColumnList dList = sharedFilesColumnModel
            .createDGuiTableColumnList();
        DTable dTable = new DTable();
        dTable.setTableColumnList(dList);
        dTable.setTableIdentifier(SHARED_FILES_TABLE_IDENTIFIER);
        dSettings.getTableList().getTableList().add(dTable);
    }

    //////////////////////////////////////////////////////////////////////////
    /// Actions
    //////////////////////////////////////////////////////////////////////////
    
    private static final String ADD_SHARE_FOLDER_ACTION_KEY = "AddShareFolderAction";
    private static final String REMOVE_SHARE_FOLDER_ACTION_KEY = "RemoveShareFolderAction";
    private static final String RESCAN_ACTION_KEY = "RescanAction";
    private static final String VIEW_BITZI_ACTION_KEY = "ViewBitziTicketAction";
    private static final String EXPORT_ACTION_KEY = "ExportAction";
    private static final String FILTER_ACTION_KEY = "FilterAction";
    private static final String OPEN_FILE_ACTION_KEY = "OpenFileAction";
    private static final String EXPLORE_FOLDER_ACTION_KEY = "ExploreFolderAction";
    
    
    class RescanAction extends FWAction
    {
        RescanAction()
        {
            super(Localizer.getString("LibraryTab_Rescan"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon(
                "Library.Refresh"), Localizer.getString("LibraryTab_TTTRescan"));
        }
        
        public void actionPerformed(ActionEvent e)
        {
            sharingTreeModel.updateFileSystem();
            GUIActionPerformer.rescanSharedFiles();
        }

        /**
         * @see phex.gui.actions.FWAction#refreshActionState()
         */
        public void refreshActionState()
        {
        }
    }
    
    private class ExportAction extends FWAction
    {
        ExportAction()
        {
            super(Localizer.getString("LibraryTab_Export"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon(
                "Library.Export"), Localizer.getString("LibraryTab_TTTExport"));
        }
        
        public void actionPerformed(ActionEvent e)
        {
            ExportDialog dialog = new ExportDialog();
            dialog.setVisible(true);
        }

        /**
         * @see phex.gui.actions.FWAction#refreshActionState()
         */
        public void refreshActionState()
        {
        }
    }
    
    private class OpenFileAction extends FWAction
    {
        OpenFileAction()
        {
            super(Localizer.getString("LibraryTab_OpenFile"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon(
                "Library.OpenFile"), Localizer.getString("LibraryTab_TTTOpenFile"));
            refreshActionState();
        }
        
        public void actionPerformed(ActionEvent e)
        {
            try
            {
                int row = sharedFilesTable.getSelectedRow();
                row = sharedFilesTable.convertRowIndexToModel(row);
                if ( row < 0 )
                {
                    return;
                }
                Object obj = sharedFilesModel.getValueAt(row, SharedFilesTableModel.FILE_MODEL_INDEX);            
                if ( obj == null )
                {
                    return;
                }
                final File file;
                if ( obj instanceof ShareFile )
                {
                    ShareFile sFile = (ShareFile)obj;
                    file = sFile.getSystemFile();
                    
                }
                else if ( obj instanceof File )
                {
                    file = (File)obj;
                }
                else
                {
                    return;
                }
                
                Runnable runnable = new Runnable()
                {
                    public void run()
                    {
                        try
                        {
                            SystemShellExecute.launchFile( file );
                        }
                        catch ( IOException exp )
                        {// ignore and do nothing..
                        }
                        catch ( Throwable th )
                        {
                            NLogger.error(NLoggerNames.USER_INTERFACE, th, th);
                        }
                    }
                };
                ThreadPool.getInstance().addJob(runnable, "SystenShellExecute");
            }
            catch ( Throwable th )
            {
                NLogger.error(NLoggerNames.USER_INTERFACE, th, th);
            }
        }

        /**
         * @see phex.gui.actions.FWAction#refreshActionState()
         */
        public void refreshActionState()
        {
            int row = sharedFilesTable.getSelectedRow();
            row = sharedFilesTable.convertRowIndexToModel(row);
            if ( row < 0 )
            {
                setEnabled(false);
                return;
            }
            Object obj = sharedFilesModel.getValueAt(row, SharedFilesTableModel.FILE_MODEL_INDEX);            
            if ( obj == null )
            {
                setEnabled(false);
                return;
            }
            if ( obj instanceof ShareFile ||  obj instanceof File  )
            {
                setEnabled(true);
            }
            else
            {
                setEnabled(false);
            }
        }
    }
    
    private class ViewBitziTicketAction extends FWAction
    {
        public ViewBitziTicketAction()
        {
            super( Localizer.getString( "ViewBitziTicket" ),
                GUIRegistry.getInstance().getPlafIconPack().getIcon("Library.ViewBitzi"),
                Localizer.getString( "TTTViewBitziTicket" ) );
            refreshActionState();
        }

        public void actionPerformed( ActionEvent e )
        {
            int row = sharedFilesTable.getSelectedRow();
            row = sharedFilesTable.convertRowIndexToModel(row);
            if ( row < 0 )
            {
                return;
            }
            
            Object obj = sharedFilesModel.getValueAt(row, SharedFilesTableModel.FILE_MODEL_INDEX);
            
            if ( obj == null || !(obj instanceof ShareFile) )
            {
                return;
            }
            ShareFile sFile = (ShareFile)obj;
            URN urn = sFile.getURN();
            String url = URLUtil.buildBitziLookupURL( urn );
            try
            {
                BrowserLauncher.openURL( url );
            }
            catch ( IOException exp )
            {
                NLogger.warn(NLoggerNames.USER_INTERFACE, exp);

                Object[] dialogOptions = new Object[]
                {
                    Localizer.getString( "Yes" ),
                    Localizer.getString( "No" )
                };

                int choice = JOptionPane.showOptionDialog( LibraryTab.this,
                    Localizer.getString( "FailedToLaunchBrowserURLInClipboard" ),
                    Localizer.getString( "FailedToLaunchBrowser" ),
                    JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null,
                    dialogOptions, Localizer.getString( "Yes" ) );
                if ( choice == 0 )
                {
                    Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
                        new StringSelection( url ), null);
                }
            }
        }

        public void refreshActionState()
        {
            int row = sharedFilesTable.getSelectedRow();
            row = sharedFilesTable.convertRowIndexToModel(row);
            if ( row < 0 )
            {
                setEnabled( false );
                return;
            }
            Object obj = sharedFilesModel.getValueAt(row, SharedFilesTableModel.FILE_MODEL_INDEX);
            if ( obj == null || !(obj instanceof ShareFile) )
            {
                setEnabled( false );
            }
            else
            {
                setEnabled( true );
            }            
        }
    }

    private class FilterAction extends FWAction
    {
        public FilterAction()
        {
            super( Localizer.getString( "LibraryTab_Filter" ),
                GUIRegistry.getInstance().getPlafIconPack().getIcon("Library.Filter"),
                Localizer.getString( "LibraryTab_TTTFilter" ) );
        }
        
        public void actionPerformed(ActionEvent e)
        {
            FilterLibraryDialog dialog = new FilterLibraryDialog();
            dialog.setVisible(true);
        }

        /**
         * @see phex.gui.actions.FWAction#refreshActionState()
         */
        public void refreshActionState()
        {            
        }
    }
    
    private class ExploreFolderAction extends FWAction
    {
        ExploreFolderAction()
        {
            super(Localizer.getString("LibraryTab_Explore"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon("Library.Explore"),
                Localizer.getString("LibraryTab_TTTExplore"));
        }
        
        public void actionPerformed(ActionEvent e)
        {
            TreePath selectionPath = mainTree.getSelectionPath();
            if ( selectionPath == null )
            {
                return;
            }
            Object lastPathComponent = selectionPath.getLastPathComponent();
            if ( !(lastPathComponent instanceof LibraryNode ))
            {
                return;
                
            }
            final File dir = ((LibraryNode)lastPathComponent).getSystemFile();
            if ( dir == null )
            {
                return;
            }
            
            try
            {
                SystemShellExecute.exploreFolder(dir);
            }
            catch (IOException exp)
            {// ignore and do nothing..
            }
        }

        /**
         * @see phex.gui.actions.FWAction#refreshActionState()
         */
        public void refreshActionState()
        {
            TreePath selectionPath = mainTree.getSelectionPath();
            if ( selectionPath == null )
            {
                setEnabled(false);
                return;
            }
            Object lastPathComponent = selectionPath.getLastPathComponent();
            if ( !(lastPathComponent instanceof LibraryNode ))
            {
                setEnabled(false);
                return;
            }
            File file = ((LibraryNode)lastPathComponent).getSystemFile();
            if ( file == null )
            {
                setEnabled(false);
                return;
            }
            setEnabled(true);
        }
    }
    
    /**
     * Starts a download.
     */
    private class AddShareFolderAction extends FWAction
    {
        AddShareFolderAction()
        {
            super( Localizer.getString("LibraryTab_Share"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon( "Library.ShareFolder"), 
                Localizer.getString("LibraryTab_TTTShare"));
        }

        public void actionPerformed(ActionEvent e)
        {
            try
            {
                File currentDirectory = null;
                TreePath selectionPath = mainTree.getSelectionPath();
                if ( selectionPath != null )
                {
                    Object lastPathComponent = selectionPath.getLastPathComponent();
                    if ( lastPathComponent instanceof LibraryNode )
                    {
                        currentDirectory = ((LibraryNode)lastPathComponent).getSystemFile();
                    }
                }
                
                final File[] files = FileDialogHandler.openMultipleDirectoryChooser( 
                    LibraryTab.this,
                    Localizer.getString( "LibraryTab_SelectDirectoryToShare" ),
                    Localizer.getString( "LibraryTab_Select" ), 
                    Localizer.getChar( "LibraryTab_SelectMnemonic" ),
                    currentDirectory,
                    Localizer.getString( "LibraryTab_CopyrightWarnTitle" ),
                    Localizer.getString( "LibraryTab_CopyrightWarnMessage" ) );
                if ( files == null )
                {
                    return;
                }
                Runnable runner = new Runnable()
                {
                    public void run()
                    {
                        try
                        {
                            for ( int i = 0; i < files.length; i++ )
                            {
                                if ( files[i] != null )
                                {
                                    shareDirRecursive(files[i]);
                                }
                            }
                            GUIActionPerformer.rescanSharedFiles();
                        }
                        catch ( Throwable th )
                        {
                            NLogger.error(NLoggerNames.USER_INTERFACE, th, th );
                        }
                    }
                };
                ThreadPool.getInstance().addJob(runner, "AddShareFolderAction");
            }
            catch ( Throwable th )
            {
                NLogger.error(NLoggerNames.USER_INTERFACE, th, th );
            }
        }

        public void refreshActionState()
        {
        }
        
        private void shareDirRecursive(File file)
        {
            if (!file.isDirectory())
            {
                return;
            }
            ServiceManager.sCfg.sharedDirectoriesSet.add(file
                .getAbsolutePath());
            File[] dirs = file.listFiles(new DirectoryOnlyFileFilter());
            for (int i = 0; i < dirs.length; i++)
            {
                shareDirRecursive(dirs[i]);
            }
        }
    }
    
    private class RemoveShareFolderAction extends FWAction
    {
        RemoveShareFolderAction()
        {
            super( Localizer.getString("LibraryTab_StopShare"), 
                GUIRegistry.getInstance().getPlafIconPack().getIcon("Library.ShareFolderClear"), 
                Localizer.getString("LibraryTab_TTTStopShare"));
            refreshActionState();
        }

        public void actionPerformed(ActionEvent e)
        {
            TreePath selectionPath = mainTree.getSelectionPath();
            if ( selectionPath == null )
            {
                return;
            }
            Object lastPathComponent = selectionPath.getLastPathComponent();
            if ( !(lastPathComponent instanceof LibraryNode ))
            {
                return;
                
            }
            final File file = ((LibraryNode)lastPathComponent).getSystemFile();
            if ( file == null )
            {
                return;
            }
            Runnable runner = new Runnable()
            {
                public void run()
                {
                    stopShareDirRecursive(file);
                    GUIActionPerformer.rescanSharedFiles();
                }
            };
            ThreadPool.getInstance().addJob(runner, "RemoveShareFolderAction");
            refreshActionState();
        }
        
        private void stopShareDirRecursive(File file)
        {
            if (!file.isDirectory())
            {
                return;
            }
            ServiceManager.sCfg.sharedDirectoriesSet.remove(file.getAbsolutePath());
            SharedFilesService sharedFilesService = ShareManager
                .getInstance().getSharedFilesService();
            SharedDirectory directory = sharedFilesService.getSharedDirectory(file);
            if (directory == null)
            {
                // in case there is no shared directory here..
                // we can assume there is no shared subdirectory available.
                return;
            }
            
            File[] dirs = file.listFiles(new DirectoryOnlyFileFilter());
            for (int i = 0; i < dirs.length; i++)
            {
                stopShareDirRecursive(dirs[i]);
            }
        }

        public void refreshActionState()
        {
            TreePath selectionPath = mainTree.getSelectionPath();
            if ( selectionPath == null )
            {
                setEnabled(false);
                return;
            }
            Object lastPathComponent = selectionPath.getLastPathComponent();
            if ( !(lastPathComponent instanceof LibraryNode ))
            {
                setEnabled(false);
                return;
            }
            File file = ((LibraryNode)lastPathComponent).getSystemFile();
            if ( file == null )
            {
                setEnabled(false);
                return;
            }
            setEnabled(true);
        }
    }

    //////////////////////////////////////////////////////////////////////////
    /// Listeners
    //////////////////////////////////////////////////////////////////////////

    private class SelectionHandler implements ListSelectionListener,
        TreeSelectionListener
    {
        public void valueChanged(ListSelectionEvent e)
        {
            if (!e.getValueIsAdjusting())
            {
                refreshTabActions();
            }
        }

        public void valueChanged( TreeSelectionEvent e )
        {
            final Object treeRoot = sharingTreeModel.getRoot();
            final Object lastPathComponent = e.getPath().getLastPathComponent();
            if ( lastPathComponent == treeRoot )
            {
                EventQueue.invokeLater( new Runnable()
                {
                    public void run()
                    {
                        mainTree
                            .setSelectionPath( new TreePath(
                                new Object[]
                                { treeRoot,
                                    sharingTreeModel.getChild( treeRoot, 0 ) } ) );
                    }
                } );
                return;
            }

            // run in separate thread.. not event thread to make sure tree selection
            // changes immediately while table needs a little more to update.
            ThreadPool.getInstance().addJob( new Runnable()
            {
                public void run()
                {
                    if ( lastPathComponent instanceof LibraryNode )
                    {
                        // then fill data..
                        sharedFilesModel
                            .setDisplayDirectory( ((LibraryNode) lastPathComponent)
                                .getSystemFile() );
                    }
                    else
                    {
                        sharedFilesModel.setDisplayDirectory( null );
                    }
                }
            }, "LibraryTableUpdate" );
            refreshTabActions();
        }
    }

    private class SharedFilesChangeHandler implements ShareChangeListener
    {
        /**
         * Called if a shared files changed.
         */
        public void sharedDirectoriesChanged()
        {
            updateLabel();
        }

        private void updateLabel()
        {
            SharedFilesService sharedFilesService = ShareManager.getInstance().getSharedFilesService();
            StringBuffer buffer = new StringBuffer();
            buffer.append( '(' );
            buffer.append( sharedFilesService.getFileCount() );
            buffer.append( " / " );
            buffer.append( NumberFormatUtils.formatSignificantByteSize(  
                ((long)sharedFilesService.getTotalFileSizeInKb()) * 1024L ) ).append( ')' );

            sharedFilesLabel.setText( buffer.toString() );
        }
    }

    private class MouseHandler extends MouseAdapter implements MouseListener
    {
        public void mouseClicked(MouseEvent e)
        {
        }

        public void mouseReleased(MouseEvent e)
        {
            if (e.isPopupTrigger())
            {
                popupMenu((Component) e.getSource(), e.getX(), e.getY());
            }
        }

        public void mousePressed(MouseEvent e)
        {
            if (e.isPopupTrigger())
            {
                popupMenu((Component) e.getSource(), e.getX(), e.getY());
            }
        }

        private void popupMenu(Component source, int x, int y)
        {
            if (source == mainTree)
            {
                refreshTabActions();
                fileTreePopup.show(source, x, y);
            }
            else if (source == sharedFilesTable )
            {
                refreshTabActions();
                fileTablePopup.show(source, x, y);
            }
        }
    }
}