//This file has been modified by Nimish Jain on March 03, 2006 at 1930 Hrs IST

/*
 *  PHEX - The pure-java Gnutella-servent.
 *  Copyright (C) 2001 - 2005 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 java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.xml.bind.JAXBException;

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.*;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import java.io.FileOutputStream;

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;
    
    //Nimish
    private Object lastSelectedTreeNode;
    
    public LibraryTab() {
        super(MainFrame.LIBRARY_TAB_ID, Localizer.getString("Library"),
                GUIRegistry.getInstance().getIconFactory().getIcon("Library"),
                Localizer.getString("TTTLibrary"), Localizer
                .getChar("LibraryMnemonic"), KeyStroke.getKeyStroke(Localizer
                .getString("LibraryAccelerator")), MainFrame.LIBRARY_TAB_INDEX);
    }
    
    public void initComponent(XJBGUISettings 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 );
        
        //Nimish
        action = getTabAction( CLOSE_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 );
        
        //Nimish
        /*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(XJBGUISettings 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();
        XJBGUITable xjbTable = GUIUtils.getXJBGUITableByIdentifier(guiSettings,
                SHARED_FILES_TABLE_IDENTIFIER);
        buildSharedFilesTableColumnModel(xjbTable);
        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 );
        
        //Nimish
        action = new CloseFileAction();
        addTabAction( CLOSE_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 );
        
        //Nimish
        new AddShareFolderAction1();
        
        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(XJBGUITable tableSettings) {
        int[] columnIds = SharedFilesTableModel.getColumnIdArray();
        XJBGUITableColumnList columnList = null;
        if (tableSettings != null) {
            columnList = tableSettings.getTableColumnList();
        }
        
        sharedFilesColumnModel = new FWTableColumnModel(sharedFilesModel,
                columnIds, columnList);
    }
    
    public void appendXJBGUISettings(XJBGUISettings xjbSettings)
    throws JAXBException {
        super.appendXJBGUISettings(xjbSettings);
        
        XJBGUITableColumnList xjbList = sharedFilesColumnModel
                .createXJBGUITableColumnList();
        ObjectFactory objFactory = new ObjectFactory();
        XJBGUITable xjbTable = objFactory.createXJBGUITable();
        xjbTable.setTableColumnList(xjbList);
        xjbTable.setTableIdentifier(SHARED_FILES_TABLE_IDENTIFIER);
        xjbSettings.getTableList().getTableList().add(xjbTable);
    }
    
    //////////////////////////////////////////////////////////////////////////
    /// 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";
    //Nimish
    private static final String CLOSE_FILE_ACTION_KEY = "CloseFileAction";
    private static final String EXPLORE_FOLDER_ACTION_KEY = "ExploreFolderAction";
    
    
    class RescanAction extends FWAction {
        RescanAction() {
            super(Localizer.getString("LibraryTab_Rescan"),
                    GUIRegistry.getInstance().getIconFactory().getIcon(
                    "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().getIconFactory().getIcon(
                    "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().getIconFactory().getIcon(
                    "Open"), Localizer.getString("LibraryTab_TTTOpenFile"));
            refreshActionState();
        }
        
        public void actionPerformed(ActionEvent e) {
            try {
                //Nimish
                File file=null;
                int row[]=sharedFilesTable.getSelectedRows();
                String files[];
                if(row.length>1) {
                    files=new String[row.length];
                    for (int i=0;i<row.length;i++) {
                        Object obj = sharedFilesModel.getValueAt(row[i], SharedFilesTableModel.FILE_MODEL_INDEX);
                        if ( obj instanceof ShareFile ) {
                            ShareFile sFile = (ShareFile)obj;
                            file = sFile.getSystemFile();
                            
                        } else if ( obj instanceof File ) {
                            file = (File)obj;
                        }
                        files[i]=file.getCanonicalPath();
                    }
                    file=new File(System.getProperty("user.home")+"\\FunToosh\\playlist.m3u");
                    FileOutputStream fos=new FileOutputStream(file);
                    for (int i=0;i<files.length;i++) {
                        if(isAudio(files[i])) {
                            fos.write(new String(files[i]+"\n").getBytes());
                        }
                    }
                    fos.close();
                } else {
                    int row1 = sharedFilesTable.getSelectedRow();
                    row1 = sharedFilesTable.convertRowIndexToModel(row1);
                    if ( row1 < 0 ) {
                        return;
                    }
                    Object obj = sharedFilesModel.getValueAt(row1, SharedFilesTableModel.FILE_MODEL_INDEX);
                    if ( obj == null ) {
                        return;
                    }
                    
                    if ( obj instanceof ShareFile ) {
                        ShareFile sFile = (ShareFile)obj;
                        file = sFile.getSystemFile();
                        
                    } else if ( obj instanceof File ) {
                        file = (File)obj;
                    } else {
                        return;
                    }
                }
                
                final File file1=file;
                
                /*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( file1 );
                        } 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);
            }
        }
        
        //Nimish added this method to check for audio file type
        public boolean isAudio(String fileName) {
            if(fileName.endsWith(".mp3") || fileName.endsWith(".MP3")) {
                return true;
            } else if(fileName.endsWith(".aif") || fileName.endsWith(".AIF")) {
                return true;
            } else if(fileName.endsWith(".aifc") || fileName.endsWith(".AIFC")) {
                return true;
            } else if(fileName.endsWith(".aiff") || fileName.endsWith(".AIFF")) {
                return true;
            } else if(fileName.endsWith(".ape") || fileName.endsWith(".APE")) {
                return true;
            } else if(fileName.endsWith(".apl") || fileName.endsWith(".APL")) {
                return true;
            } else if(fileName.endsWith(".au") || fileName.endsWith(".AU")) {
                return true;
            } else if(fileName.endsWith(".lqt") || fileName.endsWith(".LQT")) {
                return true;
            } else if(fileName.endsWith(".mac") || fileName.endsWith(".MAC")) {
                return true;
            } else if(fileName.endsWith(".med") || fileName.endsWith(".MED")) {
                return true;
            } else if(fileName.endsWith(".mid") || fileName.endsWith(".MID")) {
                return true;
            } else if(fileName.endsWith(".midi") || fileName.endsWith(".MIDI")) {
                return true;
            } else if(fileName.endsWith(".mod") || fileName.endsWith(".MOD")) {
                return true;
            } else if(fileName.endsWith(".mpa") || fileName.endsWith(".MPA")) {
                return true;
            } else if(fileName.endsWith(".mpga") || fileName.endsWith(".MPGA")) {
                return true;
            } else if(fileName.endsWith(".mpl") || fileName.endsWith(".MPL")) {
                return true;
            } else if(fileName.endsWith(".ogg") || fileName.endsWith(".OGG")) {
                return true;
            } else if(fileName.endsWith(".ra") || fileName.endsWith(".RA")) {
                return true;
            } else if(fileName.endsWith(".ram") || fileName.endsWith(".RAM")) {
                return true;
            } else if(fileName.endsWith(".rm") || fileName.endsWith(".RM")) {
                return true;
            } else if(fileName.endsWith(".rmi") || fileName.endsWith(".RMI")) {
                return true;
            } else if(fileName.endsWith(".rmj") || fileName.endsWith(".RMJ")) {
                return true;
            } else if(fileName.endsWith(".snd") || fileName.endsWith(".SND")) {
                return true;
            } else if(fileName.endsWith(".vqf") || fileName.endsWith(".VQF")) {
                return true;
            } else if(fileName.endsWith(".wav") || fileName.endsWith(".WAV")) {
                return true;
            } else if(fileName.endsWith(".wma") || fileName.endsWith(".WMA")) {
                return true;
            }
            return false;
        }
        
        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);
            }
        }
        
    }
    //Nimish Added this class to delete a file
    private class CloseFileAction extends FWAction {
        CloseFileAction() {
            super(Localizer.getString("LibraryTab_DeleteFile"),
                    GUIRegistry.getInstance().getIconFactory().getIcon(
                    "Remove"), Localizer.getString("LibraryTab_TTTDeleteFile"));
            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 {
                            int option = JOptionPane.showConfirmDialog(GUIRegistry.getInstance().getMainFrame(),"Do You really wnat to Delete this File?\nThis file will be permanently removed from your system.","Warning",JOptionPane.YES_NO_OPTION);
                            if(option==JOptionPane.OK_OPTION) {
                                file.delete();
                                JOptionPane.showMessageDialog(GUIRegistry.getInstance().getMainFrame(),"The selected File has been removed from your System.","File Removed",JOptionPane.INFORMATION_MESSAGE);
                            }
                        } catch ( Exception exp ) {// ignore and do nothing..
                            exp.printStackTrace();
                            JOptionPane.showMessageDialog(GUIRegistry.getInstance().getMainFrame(),exp.getMessage(),"Sorry",JOptionPane.ERROR_MESSAGE);
                        } 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);
            }
            sharingTreeModel.updateFileSystem();
            GUIActionPerformer.rescanSharedFiles();
            sharedFilesTable.repaint();
            tabSelectedNotify();
        }
        
        /**
         * @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().getIconFactory().getIcon("Bitzi"),
                    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().getIconFactory().getIcon("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().getIconFactory().getIcon("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().getIconFactory().getIcon( "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]);
            }
        }
    }
    
    //Class added by Nimish
    private class AddShareFolderAction1 {
        File[] files=new File[1];
        AddShareFolderAction1() {
            
            try {
                File currentDirectory = null;
                TreePath selectionPath = mainTree.getSelectionPath();
                if ( selectionPath != null ) {
                    Object lastPathComponent = selectionPath.getLastPathComponent();
                    if ( lastPathComponent instanceof LibraryNode ) {
                        currentDirectory = ((LibraryNode)lastPathComponent).getSystemFile();
                    }
                }
                
                
                files[0]=new File(ServiceManager.sCfg.mDownloadDir);
                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().getIconFactory().getIcon("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..
                        //Nimish
                        lastSelectedTreeNode=lastPathComponent;
                        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);
            }
        }
    }
    
    //Nimish overloaded this method from FWTab to force rescan of sharedFilesModel
    public void tabSelectedNotify() {
        try{
            if(lastSelectedTreeNode!=null)
        sharedFilesModel.setDisplayDirectory(((LibraryNode) lastSelectedTreeNode).getSystemFile() );
        }catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}